1. 程式人生 > >【MVC】ASP.NET MVC ViewModel

【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邏輯程式碼的需求,否則這些程式碼是必需的。

這意味著該檢視唯一責任或關注點是呈現該單個ViewModel物件,幫助更清晰地分離關注點(SoC)。關注點是具有特定目的(即關注點)的應用程式的不同方面,並且保持這些方面不同意味著您的應用程式更加有組織,程式碼更專注。將資料操作程式碼放在遠離檢視和控制器的位置,強制執行SoC。

在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 < stringstring >
        StateDictionary = new Dictionary < stringstring > {
      { “選擇...”“” }
    ,{ “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物件更靈活地訪問多個數據源。