在 ASP.NET MVC 中补充 ViewModel
我有一个由许多用户控件组成的页面。该页面的视图模型相当复杂。
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 架构的一部分。
I have a page that is made up of many user controls. The view model for this page is rather complex.
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; }
}
This page also has an PostModel that contains information for filtering, sorting, etc.
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; }
}
The simple PostModel is validated and then the controller opens 3+ repositories making multiple calls into each and builds the view model. To say the least my controller action has gotten quite large.
This is by far the most complex page I've worked on and I'm having a hard time deciding how to make it simpler.
My first thought was to create a view model factory that, after binding validation, would call into the repositories and return the ViewModel.
Then I thought about creating a custom model binder that would validate the PostModel and then hydrate the ViewModel in one step.
So my question is how do you hydrate a complex view model?
And while I write this I had the idea of using Html.RenderAction and creating a model for each of the user controls that make up this beast of a page.
Update:
The repositories make calls into WCF services, the application is part of a larger SOA arch.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一些一般提示。数据可以分为几类:系统范围、会话范围、请求范围。
系统范围数据是需要呈现给用户但对于每个用户都是相同的数据。博客应用程序的一个示例是标签云或类别列表。我认为这些数据不需要流经控制器或操作,因为它与用户交互无关。 View 本身可以调用知道如何获取(最好是缓存)此数据的 HtmlHelper(或 LayoutDataHelper)。
会话范围数据可以使用填充 ViewData.Model 字段的 ActionFilters 进行处理。它与动作的参数没有直接关系。例如,用户名。我更喜欢以下形式的属性:
请求范围/特定的所有其他内容都必须在操作中填充。然而,这并不意味着你必须有一种大规模的行动方法才能做到这一点。我会看看你的 ViewModel 是如何组成的。正如您所建议的,如果您有需要填充的控件,则 ViewModel 中的信息很可能可以分组为相关的集合。因此,您可能有一个仅组成其他较小视图模型(“部分视图模型”)的 ViewModel。然后,我将分解逻辑以将每个部分视图模型(以及任何其他复杂逻辑)填充到其自己的可重用和隔离的方法中。
处理帖子时也适用类似的抽象,尽管我担心发布大量不相关数据的页面的可用性。您应该能够使用
ActionFilters
(OnActionExecuting
) 解析相关的传入数据集(以及可选的验证)并将它们分配给操作参数。对于已发布的数据,我更喜欢过滤器而不是活页夹,除非将同一组数据发布到多个操作并且传入数据的形状始终相同。祝你好运。
Some general tips. Data can be separated into several categories: system-scope, session-scope, request-scope.
System scope data is data that needs to be presented to the user but is the same for each user. An example for a blog application would be a tag cloud, or a list of categories. I would argue that this data doesn't need to flow through the controller or action because it has nothing to do with user interaction. The View itself can call a HtmlHelper (or a LayoutDataHelper) that knows how to get (and preferably cache) this data.
Session scope data can be handled with ActionFilters that populate fields on the ViewData.Model. It is not directly related to the parameters of the action. For example, username. I prefer an attribute of the form
Everything else that is request-scope/specific must be populated in the Action. However, this doesn't mean you have to have one massive action method to do it. I would look at how your ViewModels are composed. As you suggested, if you have controls that need populating, it's likely that the information in the ViewModel can be grouped into related sets.So you might have a ViewModel that just composes other smaller view models ("partial view models"). I would then decompose the logic to populate each partial view model (and any other complex logic) each into its own re-usable and isolated method.
Similar abstraction applies when dealing with posts, though I would worry about the usability of pages that post lots of unrelated data. You should be able to use
ActionFilters
(OnActionExecuting
) to parse related sets of incoming data (and optionally validating) and assign them to action parameters. I prefer filters over binders for posted data unless the same set of data is posted to multiple actions and the shape of the incoming data is always the same.Good luck.