2010-01-20 85 views
4

我有一個由許多用戶控件組成的頁面。該頁面的視圖模型相當複雜。在ASP.NET MVC中保留ViewModels

public class ComplexViewModel 
{ 
    public ObjectA ObjectAProperty { get; set; } 
    public List<Things> ListOfThings { get; set; } 
    public List<ThingCategories> ListOfThingCategories { get; set; } 
    public List<ThingTypes> ListOfThingTypes { get; set; } 
    public List<ThingOptions> ListOfThingOptions { get; set; } 
    public int ChosenThingCategoryId { get; set; } 
    public int ChosenThingTypeId { get; set; } 
    public int ChosenThingOptionId { get; set; } 
    public OtherObject ObjectData { get; set; } 
} 

此頁面還包含用於過濾的信息,排序的PostModel等

public class SimplePostModel 
{ 
    public int ChosenThingCategoryId { get; set; } 
    public int ChosenThingTypeId { get; set; } 
    public int ChosenThingOptionId { get; set; } 
    public int ChosenThingFilterTypeId { get; set; } 
    public int ChosenThingSortTypeId { get; set; } 
    public int ChosenThingOtherId { get; set; } 
    public int ChosenThingMoreId { get; set; } 
    public int ChosenThingOMGId { get; set; } 
} 

簡單PostModel被驗證,然後控制器打開3+庫使得多個呼叫到每個並生成視圖模型。說至少我的控制器行動已經變得相當大。

這是迄今爲止我工作過的最複雜的頁面,我很難決定如何使它更簡單。

我的第一個想法是創建一個視圖模型工廠,在綁定驗證後,將調用存儲庫並返回ViewModel。

然後我想到了創建一個自定義模型綁定器來驗證PostModel,然後在一個步驟中對ViewModel進行水合。

所以我的問題是你如何水合複雜的視圖模型?

而我寫這篇文章時,我想到了使用Html.RenderAction併爲構成頁面這個野獸的每個用戶控件創建一個模型。

更新:

的倉庫撥打電話到WCF服務中,該應用程序是一個更大的SOA拱的一部分。

+2

我對此使用LINQ預測。如果(1)您的存儲庫返回'IQueryable ',並且(2)您的持久層具有一流的LINQ實現,這將很有用。既然你沒有提供這方面的細節,我只想把你引到一個博客文章,我會更詳細地解釋這個想法。這些示例不使用存儲庫,但只要您的存儲庫返回'IQueryable',這個想法就完全相同。 http://blogs.teamb.com/craigstuntz/2009/12/31/38500/無論如何,請看看它是否有幫助。 – 2010-01-20 13:55:05

回答

6

一些常規提示。數據可以分爲幾類:系統範圍,會話範圍,請求範圍。

系統範圍數據是需要呈現給用戶的數據,但對於每個用戶都是相同的。博客應用程序的一個例子是標籤雲或類別列表。我會爭辯說,這些數據不需要流過控制器或操作,因爲它與用戶交互無關。視圖本身可以調用一個HtmlHelper(或者一個LayoutDataHelper),該HtmlHelper知道如何獲取(並優選緩存)這些數據。

會話範圍數據可以使用填充ViewData.Model上的字段的ActionFilters來處理。它與行動的參數沒有直接關係。例如,用戶名。我喜歡的形式

public class SessionDataFilter : ActionFilter 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     if (filterContext.Result is ViewResult) 
     { 
      var view = filterContext.Result as ViewResult; 

      // hydrate session data on view.ViewData.Model 
     } 
    } 
} 

其他一切是請求範圍/特定必須在行動中填充的屬性。但是,這並不意味着你必須有一個大規模的行動方法來做到這一點。我會看看你的ViewModel是如何組成的。正如你所建議的那樣,如果你有需要填充的控件,ViewModel中的信息可能會被分組到相關的集合中。因此,你可能有一個ViewModel,它只是組成其他小視圖模型(「局部視圖模型」)。然後,我會分解邏輯,將每個局部視圖模型(以及任何其他複雜的邏輯)分別填充到它自己的可重用和隔離的方法中。

類似的抽象方法適用於處理帖子,但我擔心發佈大量無關數據的頁面的可用性。您應該能夠使用ActionFiltersOnActionExecuting)解析相關的傳入數據集(並可選擇驗證)並將它們分配給操作參數。除了將相同的數據集發佈到多個操作並且傳入數據的形狀始終相同之外,我更喜歡過濾器過濾器以發佈數據。

祝你好運。