在ASP.NET MVC中对ViewModel进行数据绑定

4

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

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<Something>,并且(2)你的持久层有一流的LINQ实现,那么这将非常有效。由于你没有提供关于这方面的详细信息,我只能引用一个博客文章,在那里我更详细地解释了这个想法。示例不使用存储库,但只要你的存储库返回IQueryable,这个想法就是完全相同的。 http://blogs.teamb.com/craigstuntz/2009/12/31/38500/ 无论如何,请看一下,看看它是否有帮助。 - Craig Stuntz
1个回答

6
一些常规提示。数据可以分为几个类别:系统范围、会话范围和请求范围。
系统范围的数据是需要向用户呈现的,但对于每个用户都相同的数据。例如博客应用程序中的标签云或类别列表。我认为这些数据不需要通过控制器或操作流动,因为它与用户交互无关。视图本身可以调用 HtmlHelper(或LayoutDataHelper),该辅助程序知道如何获取(最好缓存)此数据。
会话范围的数据可以使用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
        }
    }
}

所有其他请求范围/特定内容必须在Action中填充。但这并不意味着您必须有一个巨大的操作方法来完成它。建议您查看ViewModels的组成方式。如果您有需要填充的控件,则ViewModel中的信息可能可以分为相关集合。因此,您可能会有一个仅由其他较小的视图模型(“部分视图模型”)组成的ViewModel。然后,我会将填充每个部分视图模型(以及任何其他复杂逻辑)的逻辑分解为可重用且独立的方法。

处理帖子时也应用类似的抽象,尽管我会担心发布大量不相关数据的页面的可用性。您应该能够使用ActionFilters(OnActionExecuting)来解析相关集合的传入数据(并可选地进行验证)并将其分配给操作参数。与绑定器相比,我更喜欢使用过滤器来处理发布的数据,除非相同的数据集被发布到多个操作,并且传入数据的形状始终相同。

祝你好运。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接