我相信在開始第 2 天的學習時,你已經(jīng)順利地完成了第 1 天的課程。
我們回顧一下第 1 天的主要關(guān)注點:
為什么選擇 ASP.NET MVC ?
ASP.NET Webforms 和 ASP.NET MVC 的對比
理解 ASP.NET MVC 的 Controller 以及 Views
提醒:如果你還沒有完成第 1 天的學習,最好先確保完成它。我們的目標是在最后一天用最佳實踐和最新技術(shù)方法來創(chuàng)建一個小的 MVC 項目。每一天的 Lab 訓(xùn)練中,我們都會比之前一天增加一些實用性的功能,這樣看起來會比之前的程序更趨于完美。
在 Lab 2 中,View 的創(chuàng)建都是偏于靜態(tài)的。然而在真實的場景中,View 展示的通常是一些動態(tài)數(shù)據(jù)。在下一個 Lab 中,我們將展示 View 中如何動態(tài)展示數(shù)據(jù)。
View 將從 Controller 中獲取以 Model 格式展示的數(shù)據(jù)。
Model
在 ASP.NET MVC 中,Model 展示的是業(yè)務(wù)數(shù)據(jù)。
ViewData 是一個字典,它存儲了 Controller 傳輸給 View 的數(shù)據(jù)。Controller 將向 ViewData 字典添加條目,然后 View 從這個字典里讀取。現(xiàn)在我們開始做一個 Demo 吧。
第一步:創(chuàng)建一個 Model 類
在 Model 文件夾下創(chuàng)建一個新的類,命名為 Employee。
public class Employee{ public string FirstName { get; set; } public string LastName { get; set; } public int Salary { get; set; }}第二步:從 Controller 中獲取 Model
在 GetView 方法中創(chuàng)建一個 Employee 對象。
Employee emp = new Employee();emp.FirstName = "Sukesh";emp.LastName="Marla";emp.Salary = 20000;注意:確保在類中使用 Using 語句將 Model 引入,否則就要在編寫程序時使用 Employee 類的全名。
using Webapplication1.Models;第三步:創(chuàng)建 ViewData 并返回 View
在 ViewData 中存儲 Employee 對象。
ViewData["Employee"] = emp;return View("MyView");第四步:在 View 中展示 Employee 數(shù)據(jù)
打開文件 MyView.cshtml。從 ViewData 中檢索 Employee 數(shù)據(jù)并展示。
<div> @{ WebApplication1.Models.Employee emp = (WebApplication1.Models.Employee)ViewData["Employee"]; } <b>Employee Details </b><br/> Employee Name : @emp.FirstName@emp.LastName <br/> Employee Salary: @emp.Salary.ToString("C")</div>第五步:測試輸出
按下 F5,測試應(yīng)用。

寫 Razor 代碼的過程中,使用花括號「『{』和『}』」和不使用花括號,有什么區(qū)別?
在 lab 3 中,@emp.FirstName 可以使用以下代碼替換。
@{ Response.Write(emp.FirstName);}如果在 @ 后沒有使用花括號,那么它僅僅是為了展示變量或者表達式的值。
為什么需要強制轉(zhuǎn)換?
ViewData 內(nèi)部承載了一些對象。每一次增加一個新值,就會把它轉(zhuǎn)換為 Object 類型。
所以每一次都需要強制轉(zhuǎn)換來獲取對象的值。
「@emp.FirstName @emp.LastName」的含義是什么?
這個意味著 LastName 展示在 FirstName 之后,并通過空格隔開。
如果只想使用一個 @ 關(guān)鍵字,能做到剛才的效果嗎?
答案是肯定的。通過語法 @(emp.FirstName+””+emp.LastName)。
為什么在 Controller 類中要硬編碼 Employee 類?
這僅僅是為了展示 demo。實際上,我們將會在數(shù)據(jù)庫,WCF ,Web Service 或者其它地方獲取數(shù)據(jù)。
什么是數(shù)據(jù)庫邏輯,數(shù)據(jù)訪問層以及業(yè)務(wù)層?
數(shù)據(jù)訪問層在 ASP.NET MVC 中是一個未顯示的層。實際上,它一直存在,但是在 MVC 的定義中從來沒包含過它。
業(yè)務(wù)層像之前所解釋的,它是 Model 的一部分。
完整的 MVC 結(jié)構(gòu)。

ViewBag 就像是 ViewData 的語法蜜糖。ViewBag 運用 C# 4.0 的動態(tài)特征,使得 ViewData 動態(tài)化。
ViewBag 內(nèi)部運用 ViewData。
第一步:創(chuàng)建 View Bag
繼續(xù) Lab 3,然后用如下代碼片段替換 Lab 3 中的第三步:
ViewBag.Employee = emp;第二步:在 View 中展示 EmployeeData
用如下的代碼片段替換 Lab3 中的第四步:
@{ WebApplication1.Models.Employee emp = (WebApplication1.Models.Employee)ViewBag.Employee;}Employee DetailsEmployee Name: @emp.FirstName @emp.LastName Employee Salary: @emp.Salary.ToString("C")第三步:測試并輸出
按下 F5 并測試應(yīng)用程序。

我們是否可以傳輸 ViewData,然后以 ViewBag 的形式獲取到?
答案是肯定的。反過來也是可以的。就像我之前所提到過的,ViewBag 僅僅是 ViewData 的語法蜜糖。
ViewData 和 ViewBag 是 Controller 與 View 之間傳輸數(shù)據(jù)的很好選擇方式。但是在實際的項目應(yīng)用中,它們之中的任何一個都不是最佳的實踐方式。現(xiàn)在我們來討論一下運用 ViewData 和 ViewBag 的缺點吧。
ViewData 中的數(shù)據(jù)類型是 Object。所以我們在使用之前需要進行正確的類型轉(zhuǎn)換。這個操作為性能帶來了額外的負擔。
如果我們嘗試將類型轉(zhuǎn)換為錯誤的類型,或者我們在檢索對象值的時候使用錯誤的 Key 值,我們將會在運行時出錯。但是對于一個好的編程實踐而言,錯誤應(yīng)該在編譯的時候就被捕獲到。
作為一個開發(fā)者,我個人認為這是一個很主要的問題。
在 MVC 中, Controller 和 View 彼此之間的連接是弱連接,松散的。
Controller 完全不會關(guān)心 View 之中發(fā)生了什么,同理,View 也完全不會關(guān)心 Controller 之中發(fā)生了什么。
從 Controller 中我們可以傳輸一個或者多個 ViewData 或者 ViewBag 值。現(xiàn)在,當一個開發(fā)者要寫一個 View 時,他需要記住 Controller 將要傳輸什么。如果一個 Controller 開發(fā)者與 View 開發(fā)者不是同一個人,那么情況將會變得更困難。因為是完全的不關(guān)心,所以這將導(dǎo)致開發(fā)過程的低效率,也有可能引起運行錯誤。
剛才上述關(guān)于 ViewData 和 ViewBag 的三點問題可以歸結(jié)于是由數(shù)據(jù)類型所引起的。ViewData 中存儲的數(shù)據(jù)類型是 「Object」。
如果以某種方式,我們能夠為傳輸在 Controller 和 View 中的數(shù)據(jù)設(shè)置數(shù)據(jù)類型,那么問題將會迎刃而解,而這種方式便是強類型 Views。
現(xiàn)在讓我們做一個 Demo。這次我們將會提升 View 的需求到下一個級別層次。如果薪水大于 15000,那么那么就展示為黃顏色,否則為綠顏色。
第一步:創(chuàng)建強類型的 View
在 View 的頂部加上如下代碼:
@model WebApplication1.Models.Employee基于這條語句,使得我們的 View 成為一個類型為 Employee 的強類型視圖。
第二步:展示數(shù)據(jù)
現(xiàn)在,在 View 中,僅僅使用 @Model 和 Dot(.) 操作就可以智能獲取 Model,即 Empolyee 的所有數(shù)據(jù)值。

寫下如下代碼來展示數(shù)據(jù):
Employee DetailsEmployee Name : @Model.FirstName @Model.LastName @if(Model.Salary>15000){ <span style="background-color:yellow"> Employee Salary: @Model.Salary.ToString("C") </span>}else{ <span style="background-color:green"> Employee Salary: @Model.Salary.ToString("C") </span>}第三步:從 Controller 的 Action 方法傳輸 Model 數(shù)據(jù)
更改 Action 方法為如下代碼片段:
Employee emp = new Employee();emp.FirstName = "Sukesh";emp.LastName="Marla";emp.Salary = 20000; return View("MyView",emp);第四步:測試并輸出

每次在 View 中的類型聲明都需要使用類的全稱嗎,即 Namespace.ClassName ?
答案是否定的。我們可以運用 「using」聲明。
@using WebApplication1.Models@model Employee我們必須總是使用強類型視圖嗎,還是我們可以偶爾使用一下 ViewData 或者 ViewBag ?
如果想實踐最佳方式,最好使用強類型視圖。
我們可以為強類型視圖的 View 使用多個 Model 類型嗎 ?
答案是否定的。在實際項目中,當我們想要在一個視圖中展示多個 Model 時,我們經(jīng)常會結(jié)束在這點上。這一需求的解決方案將在下一節(jié)中討論。
在 Lab 5 中我們已經(jīng)違反了 MVC 的準則。根據(jù) MVC, V 代表的是純粹的 UI。它應(yīng)該不包含任何的邏輯。我們已經(jīng)通過如下的三點違反了 MVC 的結(jié)構(gòu)規(guī)則:
附加了 First Name 和 Last Name,并且用它們展示了全名。這屬于邏輯操作。
以貨幣形式展示了 Salary。這屬于邏輯操作。
展示了不同工資的不同顏色。這些基于不同值的簡單的操作改變了 HTML 元素的外觀。這屬于邏輯操作。
除了以上三點,這里還有一個更值得討論的問題點。
這一種情形是,我們想要在 View 中展示不同類型的數(shù)據(jù)。比如:顯示當前登錄的用戶名稱和雇員數(shù)據(jù)。
我們可以使用如下兩種方式實現(xiàn)這個問題:
向 Employee 類增加一個 UserName 屬性。每一次我們想要在視圖中展示一個新數(shù)據(jù),我們就像 Employee 類中增加一個屬性。這似乎是不合理的,這個屬性也許和 Employee 沒有關(guān)聯(lián)。這也違反了 SOLID 的 SRP 準則。
運用 ViewBag 或者 ViewData。這個方法我們已經(jīng)在剛才討論了其弊端。
ViewModel 是 ASP.NET MVC 應(yīng)用中沒有聲明出的層。它適合于 Model 和 View 之間并且為 View 作為一個數(shù)據(jù)容器。
Model 和 ViewModel 的區(qū)別是什么?
Model 特指業(yè)務(wù)數(shù)據(jù)。它基于業(yè)務(wù)和數(shù)據(jù)結(jié)構(gòu)創(chuàng)建。ViewModel 特指 View 數(shù)據(jù)。它基于視圖 View 創(chuàng)建。
ViewModel是如何工作的?
工作原理非常簡單。
Controller 處理用戶的交互邏輯,或者簡單來說,處理用戶請求。
Controller 獲得一個或多個 Model 數(shù)據(jù)。
Controller 將決定哪個 View 為請求作出正確回應(yīng)。
Controller 將會根據(jù)視圖的需求從接收的 Model 數(shù)據(jù)中創(chuàng)建并初始化 ViewModel 對象。
Controller 將會以 ViewData/ViewBag/強類型 View 的方式傳輸 ViewModel 數(shù)據(jù)給 View。
Controller 將會返回 View。
View 和 ViewModel 將如何關(guān)聯(lián)?
View 將會是一個以 ViewModel 為強類型的視圖。
Model 和 ViewModel 將如何關(guān)聯(lián)?
Model 和 ViewModel 彼此之間應(yīng)該是獨立的。Controller 將會基于一個或多個 Model 對象來創(chuàng)建并初始化 ViewModel 對象。
讓我們做一個小的 Lab 來更好地理解它吧。
第一步:創(chuàng)建一個文件夾
在項目中命名一個文件夾,命名為 ViewModels。
第二步:創(chuàng)建 EmployeeViewModel
為了做這一步,我們先來理清一下 View 的所有需求。
First Name 和 LastName 需要合并展示,所以在展示前它們應(yīng)該是合并的。
使用貨幣形式來顯示 Amount。
不同的 Salary 展示出不同的顏色。
當前的 User Name 也要展示在視圖中。
在 ViewModels 文件夾下創(chuàng)建一個 EmployeeViewModel 類,如下所示:
public class EmployeeViewModel{
新聞熱點
疑難解答