Asp.net mvc ASP.NET MVC中的视图模型

Asp.net mvc ASP.NET MVC中的视图模型,asp.net-mvc,viewmodel,model-binding,Asp.net Mvc,Viewmodel,Model Binding,我有一个由许多用户控件组成的页面。此页面的视图模型相当复杂 public class ComplexViewModel { public ObjectA ObjectAProperty { get; set; } public List<Things> ListOfThings { get; set; } public List<ThingCategories> ListOfThingCategories { get; set; } pub

我有一个由许多用户控件组成的页面。此页面的视图模型相当复杂

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; }
}
验证简单的后模型,然后控制器打开3个以上的存储库,对每个存储库进行多次调用,并构建视图模型。至少可以说,我的控制器动作变得相当大

这是迄今为止我工作过的最复杂的页面,我很难决定如何使它更简单

我的第一个想法是创建一个视图模型工厂,在绑定验证之后,它将调用存储库并返回视图模型

然后,我考虑创建一个自定义模型绑定器,该绑定器将验证后模型,然后在一个步骤中生成ViewModel

所以我的问题是如何创建复杂的视图模型?

在我写这篇文章的时候,我想到了使用Html.RenderAction并为每个用户控件创建一个模型,这些控件构成了这个页面的野兽

更新:


存储库调用WCF服务,应用程序是更大的SOA架构的一部分

一些一般提示。数据可以分为几个类别:系统范围、会话范围、请求范围

系统范围数据是需要呈现给用户的数据,但对于每个用户都是相同的。博客应用程序的一个示例是标记云或类别列表。我认为这些数据不需要流经控制器或操作,因为它与用户交互无关。视图本身可以调用HtmlHelper(或LayoutDataHelper),它知道如何获取(最好是缓存)这些数据

会话范围数据可以使用ActionFilters进行处理,ActionFilters填充ViewData.Model上的字段。它与动作的参数没有直接关系。例如,用户名。我更喜欢形式的属性

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
        }
    }
}
必须在操作中填充请求范围/特定的所有其他内容。然而,这并不意味着你必须有一个大规模的行动方法来做到这一点。我将了解ViewModels是如何组成的。正如您所建议的,如果您有需要填充的控件,则ViewModel中的信息可能会被分组到相关的集合中。因此,您可能有一个ViewModel,它只包含其他较小的视图模型(“局部视图模型”)。然后,我将分解逻辑,将每个局部视图模型(以及任何其他复杂逻辑)填充到各自的可重用和隔离方法中

类似的抽象也适用于处理帖子,尽管我会担心发布大量无关数据的页面的可用性。您应该能够使用
ActionFilters
OnActionExecuting
)来解析相关的传入数据集(以及可选的验证),并将它们分配给操作参数。对于已发布的数据,我更喜欢使用过滤器而不是绑定器,除非将同一组数据发布到多个操作,并且传入数据的形状始终相同


祝你好运。

我使用LINQ投影进行此操作。如果(1)您的存储库返回
IQueryable
,并且(2)您的持久化层具有一流的LINQ实现,那么这将非常有用。既然你没有给出这方面的细节,我就让你看一篇博客文章,在那里我会更详细地解释这个想法。这些示例不使用存储库,但只要存储库返回
IQueryable
s,想法就完全相同。无论如何,看看它是否有用。
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
        }
    }
}