在ASP.NET MVC中保存ViewModel

时间:2010-01-20 05:09:05

标签: 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; }
    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 arch的一部分。

1 个答案:

答案 0 :(得分:6)

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

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

可以使用填充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
        }
    }
}

必须在Action中填充请求范围/特定的所有其他内容。但是,这并不意味着你必须有一个大规模的动作方法来做到这一点。我会看看你的ViewModel是如何组成的。正如您所建议的,如果您有需要填充的控件,则ViewModel中的信息可能会被分组到相关集中。因此,您可能有一个仅构成其他较小视图模型的ViewModel(“局部视图模型”)。然后,我将分解逻辑,将每个局部视图模型(以及任何其他复杂逻辑)填充到自己的可重用和隔离方法中。

类似的抽象适用于处理帖子,但我会担心发布大量无关数据的页面的可用性。您应该能够使用ActionFiltersOnActionExecuting)来解析相关的传入数据集(并可选地进行验证),并将它们分配给操作参数。除了将相同的数据集发布到多个操作并且传入数据的形状始终相同之外,我更喜欢使用过滤器而不是绑定器来发布数据。

祝你好运。