介紹
創(chuàng)新互聯(lián)公司專注于企業(yè)網(wǎng)絡(luò)營(yíng)銷推廣、網(wǎng)站重做改版、衛(wèi)東網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5開發(fā)、商城建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為衛(wèi)東等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
在看這邊文章時(shí),我們相信你已經(jīng)成功的完成了第一天的內(nèi)容。
第一天主要集中在:
選擇MVC的理由?
ASP.NET Webform 與 ASP.NET MVC的區(qū)別
了解Controller和View
注:
如果你還沒有完成前一天的內(nèi)容,請(qǐng)先去看完再過(guò)來(lái)。我們的目標(biāo)是在一天結(jié)束用最好的練習(xí)和現(xiàn)代的方法創(chuàng)建一個(gè)小的MVC項(xiàng)目。每次新的試驗(yàn)都會(huì)添加新的方法到前一個(gè)實(shí)驗(yàn)中或者讓前一個(gè)試驗(yàn)更加好。
第二天日程
從控制器傳遞到視圖
實(shí)驗(yàn)3 - 使用ViewData
討論實(shí)驗(yàn)3
實(shí)驗(yàn)4 - 使用ViewBag
討論實(shí)驗(yàn)4
用ViewData和ViewBag的問題
實(shí)驗(yàn)5 - 了解強(qiáng)類型View
討論實(shí)驗(yàn)5
了解View Model在ASP.NET MVC中的用法
ViewModel解決方案
實(shí)驗(yàn)6 - 實(shí)現(xiàn)View Model
討論實(shí)驗(yàn)6
實(shí)驗(yàn)7 - View中的集合
討論實(shí)驗(yàn)7
結(jié)論
從控制器傳遞到視圖
在實(shí)驗(yàn)2中創(chuàng)建的view非常的靜態(tài), 在現(xiàn)實(shí)場(chǎng)景中它會(huì)現(xiàn)實(shí)某些動(dòng)態(tài)數(shù)據(jù)。在下個(gè)實(shí)驗(yàn)中我們會(huì)在View中展示一些動(dòng)態(tài)數(shù)據(jù)。
View會(huì)從Controller中的模型中獲取數(shù)據(jù)。
模型
在ASP.NET MVC中模型表示業(yè)務(wù)數(shù)據(jù)。
實(shí)驗(yàn)3 - 使用ViewData
ViewData是一個(gè)字典,它將會(huì)包含在controller和view之間傳遞被傳遞的數(shù)據(jù)。Controller將會(huì)添加元素到字典中,view會(huì)從中讀取出來(lái)。讓我們來(lái)做個(gè)demo。
步驟 1 - 創(chuàng)建Model類
在Model文件夾中創(chuàng)建一個(gè)叫Employee的新類 :
public class Employee { public string FirstName { get; set; } public string LastName { get; set; } public int Salary { get; set; } }
步驟 2 - 在Controller中獲取Model
在下面GetView方法中新建Employee 對(duì)象:
Employee emp = new Employee(); emp.FirstName = "Sukesh"; emp.LastName = "Marla"; emp.Salary = 20000;
注: 要確保把using語(yǔ)句放在最上邊或者放在Employee類完整的限定名前.
using WebApplication1.Models;
步驟 3 - 創(chuàng)建ViewData 并返回View
把Employee對(duì)象存儲(chǔ)在下面的ViewData中:
ViewData["Employee"] = emp; return View("MyView");
步驟 4 - 在View中展示 Employee 數(shù)據(jù)
打開MyView.cshtml.
像下面這樣 從 ViewData中獲取Employee 數(shù)據(jù)并展示:
@{ WebApplication1.Models.Employee emp = (WebApplication1.Models.Employee)ViewData["Employee"]; } Employee Details
Employee Name : @emp.FirstName@emp.LastName
Employee Salary: @emp.Salary.ToString("C")
步驟 5 - 測(cè)試查看輸出
實(shí)驗(yàn) 3 的討論
在寫Razor code時(shí),有 括?。ㄕf(shuō)的是"{"和"}")和沒有括弧的區(qū)別?
在最新的實(shí)驗(yàn)中@emp.FirstName 可以用下面的code片斷(snippet)替換。
@{ Response.Write(emp.FirstName); }
沒有括弧的可以簡(jiǎn)單的來(lái)現(xiàn)實(shí)變量或表達(dá)式的值.
為什么必須轉(zhuǎn)換?
把對(duì)象保存在ViewData內(nèi),每次往里添加新的值,它都會(huì)裝箱到對(duì)象的類型,所以在我們從中取值的時(shí)侯做拆箱是必須的.
"@emp.FirstName @emp.LastName"是什么意思?
意思是在顯示FirstName后加一個(gè)空格,然后是LastName
我們可以只寫一個(gè)單獨(dú)的@關(guān)鍵字嗎?
答案是肯定的,然后語(yǔ)法就成了:@(emp.FirstName + " "+emp.LastName)
為什么在Controller中硬編碼Employee類?
只是用于做演示的目的。在現(xiàn)實(shí)中我們很可能會(huì)從數(shù)據(jù)庫(kù),wcf,web或者其它地方獲取。
Database 邏輯/數(shù)據(jù)訪問層 和業(yè)務(wù)層是如何的呢?
在ASP.NET MVC中數(shù)據(jù)訪問層是不言而喻的。塔一直都在但從沒有包含在MVC的定義中。
像之前解釋的一樣,業(yè)務(wù)層屬於Model的一部分.
完整的MVC結(jié)構(gòu)
實(shí)驗(yàn) 4 - 使用ViewBag
ViewBag是可視數(shù)據(jù)只是一個(gè)語(yǔ)法糖。ViewBag采用C# 4.0 動(dòng)態(tài)特性并使ViewData保持動(dòng)態(tài)。
步驟 1 - 創(chuàng)建 View bag
繼續(xù)使用實(shí)驗(yàn)3 中 并用下面code片斷替換步驟3。
ViewBag.Employee = emp; return View("MyView");
步驟 2 - 在view中顯示 EmployeeData
用下面的code片段替換步驟4中的code
@{ WebApplication1.Models.Employee emp = (WebApplication1.Models.Employee)ViewBag.Employee; }http://lybing.blog.51cto.com/user_index.php?action=addblog&job=modify&tid=1746540 Employee Details Employee Name: @emp.FirstName @emp.LastName Employee Salary: @emp.Salary.ToString("C")
步驟 3 - 測(cè)試輸出:
實(shí)驗(yàn) 4
我們可以用ViewBag傳遞和獲取ViewData?
是的,我們可以,反之也可以。像我之前講的,ViewBag是個(gè)為了動(dòng)態(tài)顯示數(shù)據(jù)的語(yǔ)法糖。
用ViewData和ViewBag的問題所在?
在Controller和View之間傳遞值用ViewData和ViewBag是一個(gè)很好的選擇。但在真實(shí)的項(xiàng)目中不常這么做。我們來(lái)討論下有什么問題.
性能問題
在ViewData內(nèi),value是object對(duì)象。在使用之前必須要轉(zhuǎn)換到正確類型,這增加了額外的性能開銷。
沒有類型安全,沒有編譯時(shí)錯(cuò)誤
如果我們?cè)讷@取value時(shí)轉(zhuǎn)換了錯(cuò)誤的類型或用了錯(cuò)誤的key,我們會(huì)得到一個(gè)運(yùn)行時(shí)錯(cuò)誤。一個(gè)好的編程實(shí)踐,錯(cuò)誤應(yīng)該在編譯時(shí)被很好的處理。
在數(shù)據(jù)發(fā)送和數(shù)據(jù)接收間沒有合適的連接
做為一個(gè)Developer,我個(gè)人認(rèn)為這個(gè)是個(gè)重要的問題。
在MVC,Controller 和View中是比較松散的聯(lián)系。Controller完全不知道在View中發(fā)生了什么,并且view也不知道Controller中發(fā)生了什么。
我們可以在Controller中傳遞一個(gè)或多ViewData/ViewBag值?,F(xiàn)在開發(fā)者在寫View時(shí),他/她必須要記住從controller中來(lái)的是什么。如果一個(gè)Controller和view開發(fā)者不同,那么就更加困難了。完全不可預(yù)知,會(huì)導(dǎo)致很多運(yùn)行時(shí)問題和低效率的開發(fā)。
實(shí)驗(yàn) 5 - 理解強(qiáng)類型View
ViewData和ViewBag的這三個(gè)問題的原因是強(qiáng)類型。ViewData內(nèi)部values的值的數(shù)據(jù)類型是Object。
如果我們可以以某種方式設(shè)置Controller和View之間需要被傳遞的數(shù)據(jù)的數(shù)據(jù)類型,那么問題就被解決了,這是強(qiáng)類型的強(qiáng)項(xiàng)。
讓我們來(lái)做個(gè)demo,這次我們將會(huì)對(duì)View有更深層次的需求。如果薪水大于15000那么就被現(xiàn)實(shí)成***?;蛘呔G色。
步驟 1 - 把view修改成強(qiáng)類型的View
添加下面語(yǔ)句在view的頂部
@model WebApplication1.Models.Employee
上面的語(yǔ)句把我們的View變成了Employee類型
步驟 2 - 顯示數(shù)據(jù)
現(xiàn)在在View內(nèi),簡(jiǎn)單輸入@Model和dot(),然后就會(huì)得到智能提示數(shù)據(jù)Model(Employee)類的屬性。
寫下下面的copy來(lái)展示數(shù)據(jù)
Employee Details Employee Name: @Model.FirstName @Model.LastName @if (Model.Salary > 15000) { Employee Salary: @Model.Salary.ToString("C"); } else { Employee Sarlary: @Model.Salary.ToString("C") }
步驟 3 - 從Controller的Action方法中傳遞Model數(shù)據(jù)
修改action方法為下面的code:
Employee emp = new Employee(); emp.FirstName = "Sukesh"; emp.LastName = "Marla"; emp.Salary = 20000; return View("MyView", emp);
實(shí)驗(yàn) 5 的討論
每次在View中輸入完整的限定類名(Namespace.ClassName)是必須的?
不是,我們可以用下面的語(yǔ)句:
@using WebApplication1.Models @model Employee
View必須一直是強(qiáng)類型嗎?或者我們可以有時(shí)可以用ViewData煌ViewBag嗎?
做為最好的實(shí)踐,應(yīng)該總是讓view保持強(qiáng)類型。
強(qiáng)類型View中可以有多個(gè)Model對(duì)象嗎?
不能,在真實(shí)項(xiàng)目中我們常常需要在一個(gè)view中的地方去展示多個(gè)model數(shù)據(jù),我們會(huì)在下個(gè)實(shí)驗(yàn)中實(shí)現(xiàn)這樣的需求.
理解ASP.NET MVC中的View Model
在實(shí)驗(yàn)5 中我們違反了MVC的原則。對(duì)于MVC來(lái)說(shuō),V是View,應(yīng)該是純粹的UI。它不應(yīng)該包含任何類型的logic。我們做的下面三件事,違反了純粹的MVC架構(gòu)原則。
附加 First name, Last name 和做為完整姓名展示 - Logic
顯示帶貨幣的薪水 - Logic
基于value用不同的顏色來(lái)顯示薪水。換句話說(shuō):基于一些值來(lái)改變HTML元素外表 - Logic
這三個(gè)問題之外的問題,會(huì)在值得討論的地方來(lái)討論。
有時(shí)我們想要在一個(gè)View中展示多個(gè)類似的數(shù)據(jù)。
例如 - 展示當(dāng)前登錄的員工信息
我們可以用下面這些方法來(lái)實(shí)現(xiàn)。
添加用戶名屬性到Employee 類 - 每次我們想要添加新數(shù)據(jù)在View中展示,添加新屬性到Employee類看似不合邏輯。這個(gè)新屬性可能于Employee相關(guān)也可能不相關(guān)。它同樣違反SOLID的SRP原則。
使用ViewBag或ViewData - 我們已經(jīng)討論了使用這個(gè)方案的問題
ViewModel是一個(gè)解決方案
在ASP.NET MVC應(yīng)用中,ViewModel是一個(gè)約定俗成的層。它用于View,Model和act之間,做為View的數(shù)據(jù)容器
Model和ViewModel的不同?
Model是一個(gè)指定數(shù)據(jù)的業(yè)務(wù)對(duì)象,是基于業(yè)務(wù)和數(shù)據(jù)結(jié)構(gòu)來(lái)創(chuàng)建的。ViewModel是一個(gè)指定數(shù)據(jù)的View,是基于View來(lái)創(chuàng)建的。
它到底是怎么工作的?
很簡(jiǎn)單。
Controller處理交互作用的Logic或者簡(jiǎn)單的工作,處理用戶的請(qǐng)求。
Controller獲取一個(gè)或多個(gè)model數(shù)據(jù)。
Controller會(huì)決定哪個(gè)view做為請(qǐng)求最合適的響應(yīng)
Controller會(huì)基于view的需求來(lái)獲取數(shù)據(jù)Model,然后創(chuàng)建和初始化ViewModel對(duì)象
Controller會(huì)通過(guò)ViewData/ViewBag/Stongly 類型的View來(lái)傳遞ViewModel數(shù)據(jù)到View
Controller會(huì)返回一個(gè)View
View和ViewModel是怎么聯(lián)系的?
View將會(huì)被封裝成一個(gè)強(qiáng)類型View:ViewModel
Model和ViewModel是怎么聯(lián)系的?
Model和ViewModel應(yīng)該是相互獨(dú)立對(duì)的。Controller將會(huì)基于一個(gè)或多個(gè)Model對(duì)象創(chuàng)建和實(shí)例化ViewModel對(duì)象
讓我們做個(gè)小實(shí)驗(yàn)來(lái)更好的理解。
實(shí)驗(yàn) 6 - 執(zhí)行ViewModel
步驟 1 - 創(chuàng)建文件夾
在項(xiàng)目中新建一個(gè)叫ViewModel的文件夾
步驟 2 - 新建Employee ViewModel
為了做這個(gè),我們先列出對(duì)于這個(gè)view的需求:
姓和名應(yīng)該被添加在之前的顯示中。
總額應(yīng)該和貨幣一起顯示
薪水應(yīng)該顯示不同的顏色(基于value)
當(dāng)前用戶名同樣也需要顯示在view中
在ViewModels文件夾中新建一個(gè)叫EmployeeViewModel的類,像:
public class EmployeeViewModel { public string EmployeeName { get; set; } public string Salary { get; set; } public string SalaryColor { get; set; } public string UserName{get;set;} }
請(qǐng)注意:在ViewModel中,F(xiàn)irstName和LastName的用一個(gè)叫EmployeeName的簡(jiǎn)單屬性來(lái)替代。Salary屬性的數(shù)據(jù)類型是一個(gè)string并且新增了兩個(gè)新的屬性:SalaryColor、UserName
步驟 3 - 在view中使用View Model
在實(shí)驗(yàn) 5 中我們創(chuàng)建了Employee類型的View,轉(zhuǎn)換為EmployeeViewModel
@using WebApplication1.ViewModels @model EmployeeViewModel
步驟 4 - 在view中顯示數(shù)據(jù)
用下面的片段來(lái)替換view中的code:
public ActionResult GetView() { Employee emp = new Employee(); emp.FirstName = "Sukesh"; emp.LastName = "Marla"; emp.Salary = 20000; EmployeeViewModel vmEmp = new EmployeeViewModel(); vmEmp.EmployeeName = emp.FirstName + " " + emp.LastName; vmEmp.Salary = emp.Salary.ToString("C"); if (emp.Salary > 15000) { vmEmp.SalaryColor = "yellow"; } else { vmEmp.SalaryColor = "green"; } vmEmp.UserName = "Admin"; return View("MyView", vmEmp); }
步驟 5 - 測(cè)試輸出
同樣的結(jié)果,但是這次的view中沒有包含任何的Logic
實(shí)驗(yàn) 6 的討論
這意味著每個(gè)Model都要一個(gè)View Model嗎?
不是,每個(gè)View會(huì)有相應(yīng)的ViewModel。
這是用來(lái)練習(xí)Model和ViewModel關(guān)系的好例子嗎?
不是,做為Model和ViewModel的一個(gè)好練習(xí),應(yīng)該是互相不獨(dú)立,不依賴的。
我們應(yīng)該總是來(lái)創(chuàng)建ViewModel?如果View沒有包含任何的展示Logic,又想要像這樣來(lái)展示Model的數(shù)據(jù)?
我們應(yīng)該總是創(chuàng)建ViewModel。每個(gè)View應(yīng)該有它自己的ViewModel,即便ViewModel中會(huì)像model一樣包含同樣的屬性。
我們來(lái)看下這種情況:View不包含任何展示Logic并且想要像上面一樣來(lái)展示Model數(shù)據(jù)。在這種情況下假定我們不創(chuàng)建ViewModel
會(huì)出現(xiàn)的問題:在未來(lái)的需求中,如果被要求在UI中添加顯示新的數(shù)據(jù) 或者需要放一些展示Logic,我們可能需要全新的UI來(lái)達(dá)到目的。
所以我們最好保存最開始的版本,并創(chuàng)建ViewModel。在這個(gè)例子中,在最初階段的ViewModel將會(huì)和Model很相似
實(shí)驗(yàn) 7 - 使用集合的View
在這個(gè)實(shí)驗(yàn)中,我們會(huì)在View中展示一個(gè)Employee的列表。
步驟 1 - 改變EmployeeViewModel類
從EmployeeViewModel中刪除UserName屬性。
public class EmployeeViewModel { public string EmployeeName { get; set; } public string Salary { get; set; } public string SalaryColor { get; set; } }
步驟 2 - 創(chuàng)建ViewModel集合
在ViewModel文件夾中新建一個(gè)EmployeeListViewModel的類:
public class EmployeeListViewModel { public ListEmployees { get; set; } public string UserName { get; set; } }
步驟 3 - 改變?yōu)閺?qiáng)類型的View
把MyView.cshtml轉(zhuǎn)換成一個(gè)EmployeeListViewModel類型
Hello @Model.UserName
@foreach (EmployeeViewModel item in Model.Employees) { Employee Name Salary } @item.EmployeeName @item.Salary
步驟 5 - 為Employee新建Business層
在這個(gè)實(shí)驗(yàn)中, 會(huì)把我們的項(xiàng)目帶到下一層深度。添加Business層到項(xiàng)目中。在Model文件夾中新建一個(gè)EmployeeBusinessLyaer的類,并添加一個(gè)叫GetEmployees的方法
public class EmployeeBusinessLayer { public ListGetEmployees() { List employees = new List (); Employee emp = new Employee(); emp.FirstName = "johnson"; emp.LastName = " fernandes"; emp.Salary = 14000; employees.Add(emp); Employee emp2 = new Employee(); emp2.FirstName = "mikefn"; emp2.LastName = "mike"; emp2.Salary = 16000; employees.Add(emp2); return employees; } }
步驟 6 - 通過(guò)Controller來(lái)傳遞數(shù)據(jù)
public ActionResult GetView() { EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel(); EmployeeBusinessLayer empBal = new EmployeeBusinessLayer(); Listemployees = empBal.GetEmployees(); List empViewModels = new List (); foreach (Employee emp in employees) { EmployeeViewModel empViewModel = new EmployeeViewModel(); empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName; empViewModel.Salary = emp.Salary.ToString("C"); if (emp.Salary > 15000) { empViewModel.SalaryColor = "yellow"; } else { empViewModel.SalaryColor = "green"; } empViewModels.Add(empViewModel); } employeeListViewModel.Employees = empViewModels; employeeListViewModel.UserName = "Admin"; return View("MyView", employeeListViewModel); }
步驟 7 - 輸出
實(shí)驗(yàn) 7 的討論
View可以是List類的強(qiáng)類型嗎?
當(dāng)然可以
為什么創(chuàng)建分開的EmployeeListViewModel類,而不是新建一個(gè)強(qiáng)類型的List
如果我們使用List直接替換EmployeeListViewModel,那么會(huì)有兩個(gè)問題。
管理將來(lái)展示的Logic
UserName屬性不是關(guān)聯(lián)單獨(dú)的Employees。而是關(guān)聯(lián)完整的View
為什么我們從EmployeeViewModel中刪除UserName屬性,讓它成為EmployeeListViewModel中的一部分呢?
所有的Employee將會(huì)有同樣的UserName屬性,把UserName放在EmployeeViewModel中只是增加冗余的code,也增中了整體數(shù)據(jù)的內(nèi)存存儲(chǔ)需要.
原文:http://www.codeproject.com/Articles/897559/Learn-MVC-in-days-Day