本文參考自:http://www.codeproject.com/Articles/986730/Learn-MVC-Project-in-days-Day
轉載請注明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。
通過第一天的學習之后,我們相信您已經對MVC有一些基本了解。
本節所講的內容是在上節的基礎之上,因此需要確保您是否掌握了上一節的內容。本章的目標是在今天學習結束時利用最佳實踐解決方案創建一個小型的MVC項目,本節的主要目標是了解MVC之間的數據傳遞問題。我們會逐步深入講解,並添加新功能,使項目越來越完善。
系列文章
七天學會ASP.NET MVC (一)——深入理解ASP.NET MVC
七天學會ASP.NET MVC (二)——ASP.NET MVC 數據傳遞
七天學會ASP.NET MVC (三)——ASP.Net MVC 數據處理
七天學會ASP.NET MVC (五)——Layout頁面使用和用戶角色管理
七天學會ASP.NET MVC (六)——線程問題、異常處理、自定義URL
Controller與 View之間的值傳遞
在上一節的實驗二中已經創建了靜態View。然而在實際使用情況下,View常用於顯示動態數據。在實驗三中們將在View中動態顯示數據。
View將從從Controller獲得Model中的數據。
Model是MVC中 表示業務數據的層。
實驗3 ——使用View數據
ViewData相當於數據字典,包含Controlle和View之間傳遞的所有數據。Controller會在該字典中添加新數據項,View從字典中讀取數據。
1. 創建Model 類
在Model文件夾下新建Employee類,如下。
1: public class Employee
2:
3: {
4: public string FirstName { get; set; }
5:
6: public string LastName { get; set; }
7:
8: public int Salary { get; set; }
9:
10: }
2. 在Controller 中獲取Model
在GetView 方法中創建Employee 對象:
1: Employee emp = new Employee();
2: emp.FirstName = "Sukesh";
3: emp.LastName="Marla";
4: emp.Salary = 20000;
注意:請確保使用Using語句包含此類,或者使用類的全稱。
1: using WebApplication1.Models;
3. 創建ViewData 並返回View
在ViewData中存儲Employee 對象。
1: ViewData["Employee"] = emp;
2: return View("MyView");
4. 在View中顯示Employee 數據
打開MyView.cshtml。
從ViewData中獲取Employee 數據並按照如下代碼顯示:
1: <div>
2: @{
3: WebApplication1.Models.Employee emp=(WebApplication1.Models.Employee)
4: ViewData["Employee"];
5: }
6:
7: <b>Employee Details </b><br />
8: Employee Name : @emp.FirstName@emp.LastName <br />
9: Employee Salary: @emp.Salary.ToString("C")
10: </div>
5. 測試輸出
按F5運行
關於實驗 3
1. 寫Razor代碼帶花括號和沒有花括號有什么區別?
在實驗三中@emp.FirstName能夠使用以下腳本來代替
1: @{
2: Response.Write(emp.FirstName);
3: }
@符號后沒有花括號只是簡單的顯示變量或表達式的值
2. 為什么需要強制轉換類型
ViewData可操作內部對象,每次添加新值,會封裝成對象類型,因此每次都需要解壓來提取值。
3. @emp.FirstName @emp.LastName有什么特殊含義?
意味着LastName顯示在FirstName之后並自動添加空格。
4. 為什么 Employee中的 硬編碼是由Controller創建的 ?
在本文中只是為了實現實驗目的,因此采用硬編碼,實際使用中,是從數據庫或Web服務中獲取的。
5. 數據庫邏輯,數據訪問層,業務層分別指的是什么?
- 數據訪問層是ASP.NET MVC中是一直隱式存在的,MVC定義中不包含數據訪問層的定義。
- 業務層是解釋器的先驅,是Model的一部分。
完整的MVC結構
實驗4——ViewBag的使用
ViewBag可以稱為ViewData的一塊關於語法的輔助的糖果,ViewBag使用C# 4.0的動態特征,使得ViewData也具有動態特性。
ViewData與ViewBag對比:
ViewData |
ViewBag |
它是Key/Value字典集合 |
它是dynamic類型對像 |
從Asp.net MVC 1 就有了 |
ASP.NET MVC3 才有 |
基於Asp.net 3.5 framework |
基於Asp.net 4.0與.net framework |
ViewData比ViewBag快 |
ViewBag比ViewData慢 |
在ViewPage中查詢數據時需要轉換合適的類型 |
在ViewPage中查詢數據時不需要類型轉換 |
有一些類型轉換代碼 |
可讀性更好 |
ViewBag內部調用ViewData。
1. 創建View Bag
在實驗三的基礎之上,使用以下腳本代替第三步中的代碼。
1: ViewBag.Employee = emp;
2. 在View中顯示EmployeeData
使用以下代碼來替代實驗三中第四步中的代碼:
1: @{
2: WebApplication1.Models.Employee emp = (WebApplication1.Models.Employee)
3: ViewBag.Employee;
4: }
5: Employee Details
6:
7: Employee Name: @emp.FirstName @emp.LastName
8:
9: Employee Salary: @emp.Salary.ToString("C")
3. 測試輸出
運行結果:
關於實驗4
可以傳遞ViewData,接收時獲取ViewBag嗎?
答案是肯定的,反之亦然。如之前所說的,ViewBag只是ViewData的一塊糖/
ViewData與ViewBag的問題
ViewData和ViewBag 是Contoller與View之間值傳遞的內容。但是在實際使用的過程中,它們並不是最佳選擇,接下來我們來看看使用它們的缺點:
- 性能問題;ViewData中的值都是對象類型,使用之前必須強制轉換為合適的類型。會添加額外的性能負擔。
- 沒有類型安全就沒有編譯時錯誤,如果嘗試將其轉換為錯誤的類型,運行時會報錯。良好的編程經驗告訴我們,錯誤必須在編譯時捕獲。
- 數據發送和數據接收之間沒有正確的連接;MVC中,Controller和View是松散的連接的。Controller是無法捕獲View變化,View也無法捕獲到Controller內部發生的變化。從Controller傳遞一個ViewData或ViewBag的值,當開發人員正在View中寫入,就必須記錄從Controller中即將獲得什么值。如果Controller與View開發人員不是相同的開發人員,開發工作會變得非常困難。會導致許多運行時問題,降低了開發效率。
實驗5——理解強類型View
ViewData和ViewBag引起的所有問題根源都在於數據類型。參數值的數據類型是被封裝在ViewData中的,稱為對象。
如果能夠設置Controller和View之間參數傳遞的數據類型,那么上述問題就會得到解決,因此從得出強類型View。
接下來,我們看一個簡單的例子,如果工資大於15000則顯示黃色,低於顯示綠色。
1. 創建View的強類型
在View的頂部添加以下代碼:
@model WebApplication1.Models.Employee
2. 顯示數據
在View內部輸入@Model.就會查看到Model類的屬性
添加以下代碼來顯示數據:
1: Employee Details
2:
3: Employee Name : @Model.FirstName @Model.LastName
4:
5: @if(Model.Salary>15000)
6: {
7: <span style="background-color:yellow">
8: Employee Salary: @Model.Salary.ToString("C")
9: </span>
10: }
11: else
12: {
13: <span style="background-color:green">
14:
15: Employee Salary: @Model.Salary.ToString("C")
16: </span>
17: }
3. 從Controller Action方法中傳遞Model數據。
修改action代碼
1: Employee emp = new Employee();
2: emp.FirstName = "Sukesh";
3: emp.LastName="Marla";
4: emp.Salary = 20000;
5: return View("MyView",emp);
4. 測試輸出
關於實驗5
View中使用類時需要聲明類的全稱嗎 (Namespace.ClassName)?
添加以下語句,就不需要添加全稱。
1: @using WebApplication1.Models
2: @model Employee
是否必須設置強類型視圖或不使用ViewData和ViewBag?
設置強類型視圖是最佳解決方案。
是否能將View設置為多個Model使用的強類型?
不可以,實際項目中在一個View中想要顯示多個Model時以點結束的。該問題的解決方法將在下一節討論。
理解ASP.NET MVC 中的View Model
實驗5中已經違反了MVC的基本准則。根據MVC,V是View純UI,不包含任何邏輯層。而我們在實驗5中以下三點違反了MVC的體系架構規則。
1. 附加姓和名顯示全名——邏輯層
2. 使用貨幣顯示工資——邏輯層
3. 使用不同的顏色表示工資值,使用簡單的邏輯改變了HTML元素的外觀。——邏輯層
ViewModel 解決方法
ViewModel是ASP.NET MVC應用中隱式聲明的層。它是用於維護Model與View之間數據傳遞的,是View的數據容器。
Model 和 ViewModel 的區別
Model是業務相關數據,是根據業務和數據結構創建的。ViewModel是視圖相關的數據。是根據View創建的。
具體的工作原理
- Controller 處理用戶交互邏輯或簡單的判斷。處理用戶需求
- Controller 獲取一個或多個Model數據
- Controller 決策哪個View最符合用戶的請求
- Controller 將根據Model數據和View需求創建並且初始化ViewModel對象。
- Controller 將ViewModel數據以ViewData或ViewBag或強類型View等對象傳遞到View中。
- Controller 返回View。
View 與 ViewModel 之間是如何關聯的?
View將變成ViewModel的強類型View。
Model和 ViewModel 是如何關聯的?
Model和ViewModel 是互相獨立的,Controller將根據Model對象創建並初始化ViewModel對象。
接下來我們來看實驗6:
實驗6—— 實現ViewModel
1. 新建文件夾
在項目中創建新文件夾並命名為ViewModels。
2. 新建EmployeeViewModel
為了達到實驗目的,首先列出我們的實驗需求:
1. 名和姓應該合並顯示。
2. 使用貨幣顯示數量
3. 薪資以不同的顏色來顯示
4. 當前登錄用戶也需要在View中顯示。
在ViewModels類中,創建新類並命名為EmployeeViewModel,如下所示:
1: public class EmployeeViewModel
2: {
3: public string EmployeeName { get; set; }
4: public string Salary { get; set; }
5: public string SalaryColor { get; set; }
6: public string UserName{get;set;}
7: }
注意,姓和名應該使用EmployeeName這一個屬性。而Salary屬性的數據類型是字符串,且有兩個新的屬性添加稱為SalaryColor和UserName。
3. View中使用ViewModel
實驗五中已經創建了View的強類型Employee。將它改為 EmployeeViewModel
1: @using WebApplication1.ViewModels
2: @model EmployeeViewModel
4. 在View中顯示數據
使用以下腳本代替View部分的內容
1: Hello @Model.UserName
2: <hr />
3: <div>
4: <b>Employee Details</b><br />
5: Employee Name : @Model.EmployeeName <br />
6: <span style="background-color:@Model.SalaryColor">
7: Employee Salary: @Model.Salary
8: </span>
9: </div>
5. 新建並傳遞ViewModel
在GetView方法中,獲取Model數據並且將強制轉換為ViewModel對象。
1: public ActionResult GetView()
2: {
3: Employee emp = new Employee();
4: emp.FirstName = "Sukesh";
5: emp.LastName="Marla";
6: emp.Salary = 20000;
7:
8: EmployeeViewModel vmEmp = new EmployeeViewModel();
9: vmEmp.EmployeeName = emp.FirstName + " " + emp.LastName;
10: vmEmp.Salary = emp.Salary.ToString("C");
11: if(emp.Salary>15000)
12: {
13: vmEmp.SalaryColor="yellow";
14: }
15: else
16: {
17: vmEmp.SalaryColor = "green";
18: }
19:
20: vmEmp.UserName = "Admin"
21:
22: return View("MyView", vmEmp);
23: }
6. 測試輸出
盡管運行結果類似,但是View中不包含任何業務邏輯。
關於實驗6
是否意味着,每個Model都有一個ViewModel?
每個View有其對應的ViewModel。
Model與ViewModel之間存在關聯是否是好的實現方法?
最好的是Model與ViewModel之間相互獨立。
需要每次都創建ViewModel嗎?假如View不包含任何呈現邏輯只顯示Model數據的情況下還需要創建ViewModel嗎?
建議是每次都創建ViewModel,每個View都應該有對應的ViewModel,盡管ViewModel包含與Model中相同的屬性。
假定一個View不包含任何呈現邏輯,只顯示Model數據,我們不創建ViewModel會發生什么?
無法滿足未來的需求,如果未來需要添加新數據,我們需要從頭開始創建全新的UI,所以如果我們保持規定,從開始創建ViewModel,就不會發生這種情況。在本實例中,初始階段的ViewModel將與Model幾乎完全相同。
實驗7——帶有集合的View
在本實驗中,在View中顯示Employee列表。
1. 修改EmployeeViewModel 類
刪除UserName屬性
1: public class EmployeeViewModel
2: {
3: public string EmployeeName { get; set; }
4: public string Salary { get; set; }
5: public string SalaryColor { get; set; }
6: }
2. 創建結合ViewModel
在ViewModels 文件下,創建新類並命名為EmployeeListViewModel
1: public class EmployeeListViewModel
2: {
3: public List<employeeviewmodel> Employees { get; set; }
4: public string UserName { get; set; }
5: }
3. 修改強類型View的類型
1: @using WebApplication1.ViewModels
2: @model EmployeeListViewModel
4. 顯示View中所有的Employee
1: <body>
2: Hello @Model.UserName
3: <hr />
4: <div>
5: <table>
6: <tr>
7: <th>Employee Name</th>
8: <th>Salary</th>
9: </tr>
10: @foreach (EmployeeViewModel item in Model.Employees)
11: {
12: <tr>
13: <td>@item.EmployeeName</td>
14: <td style="background-color:@item.SalaryColor">@item.Salary</td>
15: </tr>
16: }
17: </table>
18: </div>
19: </body>
5. 創建Employee的業務邏輯
新建類並命名為EmployeeBusinessLayer ,並帶有GetEmployees()方法。
1: public class EmployeeBusinessLayer
2: {
3: public List<employee> GetEmployees()
4: {
5: List<employee> employees = new List<employee>();
6: Employee emp = new Employee();
7: emp.FirstName = "johnson";
8: emp.LastName = " fernandes";
9: emp.Salary = 14000;
10: employees.Add(emp);
11:
12: emp = new Employee();
13: emp.FirstName = "michael";
14: emp.LastName = "jackson";
15: emp.Salary = 16000;
16: employees.Add(emp);
17:
18: emp = new Employee();
19: emp.FirstName = "robert";
20: emp.LastName = " pattinson";
21: emp.Salary = 20000;
22: employees.Add(emp);
23:
24: return employees;
25: }
26: }
27: </employee>
6.從控制器中傳參
1: public ActionResult GetView()
2: {
3: EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
4:
5: EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
6: List<employee> employees = empBal.GetEmployees();
7:
8: List<employeeviewmodel> empViewModels = new List<employeeviewmodel>();
9:
10: foreach (Employee emp in employees)
11: {
12: EmployeeViewModel empViewModel = new EmployeeViewModel();
13: empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName;
14: empViewModel.Salary = emp.Salary.ToString("C");
15: if (emp.Salary > 15000)
16: {
17: empViewModel.SalaryColor = "yellow";
18: }
19: else
20: {
21: empViewModel.SalaryColor = "green";
22: }
23: empViewModels.Add(empViewModel);
24: }
25: employeeListViewModel.Employees = empViewModels;
26: employeeListViewModel.UserName = "Admin";
27: return View("MyView", employeeListViewModel);
28: }
29: </employeeviewmodel></employeeviewmodel></employee>
7. 執行
關於實驗7
是否可以制定強類型View列表?
是的 為什么要新建EmployeeListViewModel單獨的類而不直接使用強類型View的列表?1. 策划未來會出現的呈現邏輯2. UserName屬性。UserName是與employees無關的屬性,與完整View相關的屬性。為什么刪除EmployeeViewModel 的UserName屬性,而不是將它作為EmployeeListViewModel的一部分?UserName 是相同的,不需要EmployeeViewModel中添加UserName。
結論
以上就是我們第二天所講的內容,在第三天我們會學習新內容!
數據傳遞是MVC知識的重要組成部分,深入理解了這部分知識,能夠幫助我們更好的進行MVC的開發。同時,請記得借助開發工具來助力開發過程,使用 ComponentOne Studio ASP.NET MVC 這款輕量級控件,工作效率大大提高的同時,工作量也會大大減少。
相關閱讀: