【MVC】ASP.NET MVC ViewModel
ViewModel的概念不僅適用於ASP.NET MVC,因為您將在整篇網頁中看到有關MVC,MVP和MVVM模式的文章和部落格文章中對ViewModels的引用。這些帖子和文章可以圍繞任何數量的技術,如ASP.NET,Silverlight,WPF或MVC ...本文將調查ViewModels適用於ASP.NET MVC的世界。
什麼是ASP.NET MVC ViewModel?
在ASP.NET MVC中,ViewModels允許您將來自一個或多個數據模型或源的多個實體變形為單個物件,並針對檢視的消耗和渲染進行優化。下圖展示了ViewModel的概念:
ViewModel的目的是讓檢視具有單個物件進行渲染,從而減少檢視中對UI邏輯程式碼的需求,否則這些程式碼是必需的。
在MVC中使用ViewModels可實現更精細的粒度和更好的SoC,從而提供更易於維護和可測試的程式碼。請記住,單元測試是關於測試小單元的。
隨著更好的編碼實踐,有很多商業原因說明為什麼你可能會考慮使用ViewModels:
- 將查詢資料的下拉列表合併到相關實體中
- 主細節記錄檢視
- 分頁:結合實際資料和分頁資訊
- 像購物車或使用者配置檔案小部件這樣的元件
- 儀表板,具有多個不同資料來源
- 報告,通常包含彙總資料
上述場景對於各種應用程式都很常見,並且處理比基本的CRUD格式的資料頁面更復雜的資料(例如,簡單的1:1對映到資料庫表)。例如,提供狀態列表,並確保與當前客戶狀態相匹配的狀態,意味著您需要提供兩組資料或一組客戶/狀態資料,如下圖所示。
某些場景(如代表美國狀態的查詢表)可以輕鬆地與ViewModels或ViewBag / ViewData物件一起使用,因此有時可能會有一些重疊。由應用程式架構師和開發人員決定什麼對他們的確切用例最有效。
建立一個ViewModel
儘管一個ViewModel由多個實體組成,但ViewModel的核心仍然只是一個類 - 並且它甚至不會像許多MVC類那樣繼承任何特殊的東西。
從物理上看,ViewModels可以存在於不同的位置,如下所示:
- 在名為ViewModels的資料夾中,該資料夾駐留在專案的根目錄中。(小應用程式)
- 作為從MVC專案引用的.dll(任何大小的應用程式)
- 在作為服務層的單獨專案中,用於生成檢視/內容特定資料的大型應用程式。(企業應用程式)
由於ViewModel只是一個類,因此開始使用ViewModel的最簡單方法是建立一個名為ViewModels的新資料夾併為其新增一個新的程式碼檔案。
要建立CustomerViewModel ViewModel,請將Customer和StatesDictionary型別新增為屬性以形成一個CustomerViewModel類。在下面的示例中,CustomerViewModel類包含新定義的屬性。
公共 類 CustomerViewModel
{
公共客戶{get; 組; }
public StatesDictionary States {get; 組; }
公共 CustomerViewModel(客戶客戶)
{
客戶=客戶;
States = new StatesDictionary();
}
}
通常,ViewModels包含單詞“ViewModel”作為其名稱的一部分; 然而,在這裡工作的約定是為了保持程式碼可讀性的一致性,因為MVC中的其他類也在其名稱中聲明瞭它們的意圖(例如,控制器的名稱,操作方法等...在名稱中使用約定)。
StatesDictionary類是一個簡單的Dictionary物件,它包含兩個字串型別的引數。該類還包含詞典中所有成員的定義(即狀態資料)。StatesDictionary類中唯一的屬性是StateSelectList,它是Html Helpers用來呈現顯示狀態列表的HTML <select>元素的物件。StateSelectList屬性中的型別Dictionary <string,string>分別對映到狀態縮寫和狀態名稱。
公共 類 StatesDictionary
{
公共 靜態 SelectList StateSelectList
{
get { return new SelectList(StateDictionary,“Value”,“Key”); }
}
public static readonly IDictionary < string,string >
StateDictionary = new Dictionary < string,string > {
{ “選擇...”,“” }
,{ “Alabama”,“AL” }
,{ “阿拉斯加”,“AK” }
,{ “Arizona”,“AZ” }
,{ “阿肯色州”,“AR” }
,{ “California”,“CA” }
//程式碼繼續新增狀態...
};
}
存在於所有型別的應用程式中的資料位於小列表中,並且不常發生變化,如StatesDictionary類。在現實世界的應用程式中,您會發現處理查詢資料的各種方法,例如狀態列表(通常是XML檔案和SQL表)。您可以將StateDictionary方法中的程式碼替換為使用Entity Framework中的實體,從檔案中讀取資料或您需要的任何資料訪問程式碼。
建立ViewModel後,接下來的步驟是在控制器中例項化它並將其返回到檢視。
獲取ViewModel的檢視
從控制器開始...
將ViewModel傳送到檢視進行渲染將與處理模型時的工作方式相同。由於它只是一個類,檢視不知道模型或ViewModel來自哪裡,並且不關心。您可以在控制器中建立ViewModel類的例項,或者在使用IoC容器時解析它。請記住,就像您使用檢視一樣,您應該讓控制器清理不必要的程式碼,這意味著只有取得模型或ViewModel的程式碼才屬於此處,並且只有更多。
public ActionResult Edit(int id)
{
Customer customer = context.Customers.Single(x => x.Id == id);
var customerViewModel = new CustomerViewModel(customer);
返回 View(customerViewModel);
}
然後該檢視呈現ViewModel ...
為了使檢視知道要使用哪個物件,請將@model關鍵字設定為指向ViewModel,就像您對常規模型已經使用的那樣。
@model FourthCoffee.Web.ViewModels.CustomerViewModel
由於Customer物件是ViewModel的屬性,因此您將看到model.Class.Property語法來訪問ViewModel資料,與以下程式碼行類似。
< div class =“editor-label” >
@ Html.LabelFor(model = > model.Customer.FirstName)
</ div >
< div class =“editor-field” >
@ Html.EditorFor(model = > model.Customer.FirstName)
@ Html.ValidationMessageFor(model = > model.Customer.FirstName)
</ div >
@ * ...檢視程式碼繼續渲染屬性... * @
此外,您可以編輯編輯/建立檢視,以便包含狀態列表的DropDownList將顯示,並顯示與客戶相匹配的正確狀態。
< div class =“editor-field” >
@ Html.DropDownList(“狀態”,新的SelectList(StatesDictionary.StateSelectList,
“Value”,“Text”,Model.Customer == null?“”:Model.Customer.State))
@ Html.ValidationMessageFor(model = > model.Customer.State)
</ div >正如您可能已經注意到的那樣,使用ViewModel就像使用ViewBag或ViewData物件一樣簡單。但是,ViewModels提供了更易於測試和優化的額外優勢。
檢查結果
在使用者導航到瀏覽器中的/ Customers / Edit / 1 URL後,Razor檢視引擎將呈現CustomerViewModel,類似於以下螢幕快照。
按照預期,狀態DropDownList顯示該客戶的狀態和當前狀態。
深入研究ViewModels
由於ViewModel渲染的模型類和資料庫表之間不再具有這些1:1對映的預處理資料,因此您需要自己建立對映。您可以手動對映小型ViewModels,但在對映較大的類時,特別是在處理父子孫,多級或複雜資料時,這會很快變得繁重。這就是AutoMapper等工具發揮作用的地方。通過AutoMapper,您可以更輕鬆地手動設定ViewModel和模型之間的對映,或者編寫您自己的對映器。
以下是使用ViewModels的一些技巧:
- 僅放入將在ViewModel中呈現的資料。
- 該檢視應該指導ViewModel的屬性,這樣它就更適合渲染和維護。
- 當ViewModel變得複雜時使用對映器。
一些可以幫助您為模型和ViewModel生成POCO(Plain Old CLR物件)的工具是:
除了這些工具,您還可以使用MvcScaffolding根據ViewModel建立操作和檢視。MvcScaffolding,ASP.NET團隊成員Steve Sanderson的發明,可以讓您更輕鬆快捷地建立CRUD,儲存庫,單元測試和其他模板。點選
您應該始終更喜歡使用ViewModel,而不是例項化多個模型並將該操縱程式碼放入控制器中。
概要
當您需要處理比其他物件允許的更復雜的資料時,ViewModels可幫助您組織和管理MVC應用程式中的資料。使用ViewModels可以讓您靈活地使用您認為合適的資料。ViewModels區域通常比模型+ ViewBag / ViewData物件更靈活地訪問多個數據源。