2010-01-20 83 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)解析相关的传入数据集(并可选择验证)并将它们分配给操作参数。除了将相同的数据集发布到多个操作并且传入数据的形状始终相同之外,我更喜欢过滤器过滤器以发布数据。

祝你好运。