ASP.NET MVC - 视图模型模式
我使用 MVC 框架 (ASP.NET MVC2/3/Razor) 才几个月,我真的很喜欢它,但是我很难找出视图模型的标准。在我的项目中,我有一个 Models 文件夹(包含我的数据模型 - Linq DBML、Repository[ies]、扩展方法)和 Models/ViewModels 文件夹。我的视图模型通常是可重用的类,通常只包含针对特定视图需要访问的 LINQ 对象或对象集合的简单获取/设置属性。
现在我遇到的问题是弄清楚何时创建视图模型。我的目标是尽可能频繁地使用 LINQ 对象作为视图模型,特别是当它是编辑操作时。我的问题是,如果我有其他数据位可能只想用于显示目的怎么办?我不喜欢使用 ViewData/ViewBag 集合,因为访问这些集合的成员需要了解集合项的键(对于设计师/前端人员来说“猜测”并不容易)。我也不喜欢为每个视图创建一个 ViewModel 的想法,因为它看起来像是不必要的混乱代码。
例如,假设我有一个员工的数据模型,并且我想显示一些与该员工无关的信息 - 例如,站点统计信息、动态菜单以及您能想到的可能来自数据库的任何其他信息。我应该通过什么模型来执行 /Employee/Edit 操作?带有一堆 ViewData[] 的 Employee 对象,还是自定义的 EmployeeView?
有黄金标准吗?我缺少什么?你做了什么不同的事情,我应该调查一下?提前致谢!
I have only been working with the MVC framework (ASP.NET MVC2/3/Razor) for a few months now and I am really enjoying it, however I am having a hard time figuring out a standard for View Models. In my projects, I have a Models folder (Contains my data models - Linq DBML, Repository[ies], Extension methods) and a Models/ViewModels folder. My view models are usually reusable classes which usually just contain simple get/set properties for the LINQ objects or collections of objects I need to access for a particular view.
Now the problem I am having is figuring out when to create a view model. My goal is to use the LINQ object as the view model as often as possible, especially when it is an Edit action. My problem is what if I have other bits of data that I might want to use for display purposes only? I don't like to use the ViewData/ViewBag collections, as accessing members of these requires knowledge of the collection item's key (not easy for a designer/front-end guy to "guess"). I also don't like the idea of creating a ViewModel for each View, as it seems like unnecessarily messy code.
For example, imagine I have a data model for an Employee, and I want to display some information unrelated to that employee - say, site statistics, dynamic menus, and whatever else you can think of that might come from the database. What model should I pass the /Employee/Edit action? The Employee object with a bunch of ViewData[] for the rest, or a custom EmployeeView?
Is there a gold standard? What am I missing? What are you doing different that I should look into? Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我从不直接使用实体类作为视图模型。我总是为每个视图创建一个特定于视图的模型,其中包含该视图的数据。我开始使用 AutoMapper 在视图模型和实体模型之间进行映射。我通过 ModelMapper 类进行调解,该类具有用于处理标准映射(仅调用自动映射器)的 ToViewModel() 方法和用于自定义映射的专用映射方法,特别是支持创建和更新视图模型中的实体。
I never use my entity classes directly as view models. I always create a view-specific model for each view containing the data for that view. I've started using AutoMapper to map between view models and entity models. I mediate this through a ModelMapper class that has a
ToViewModel<TEntity,TViewModel>()
method for handing standard mappings (just invokes the automapper) and specialized mapping methods for custom mappings, especially to support creating and updating entities from view models.您在这里命名了三件事:
第三点是一个陷阱;仅仅因为某些内容在您的数据库中,并不意味着它是您的域模型的一部分。
导航可能基于数据库。它也可能位于站点地图中或硬编码到应用程序中。它实际上不是应用程序数据,而是应用程序配置。如果您将其存储在应用程序数据库中,那没问题(实际上不是),但它不是模型本身的一部分。
同样,网站统计信息通常存储在数据库中,但它们存储在不同的数据库中,特别是分析数据库(许多人只是将其“外包”给Google)。再说一遍,它们是一种数据,但它们不是您的模型。
如果您希望您的应用程序有意义,您需要在概念层面上分离这些问题。导航在母版页/布局中完成,包括使其工作所需的任何动态代码。它是纯粹的视图逻辑 - 不要让它泄漏到您的模型中。对于与当前正在使用的实际功能相关的问题,使用 ViewData/ViewBag 是完全可以的,并且通常更可取。
现在,假设还有其他类型的视图数据实际上是应用程序数据:原则上确实认为视图应该直接连接到模型 - 毕竟这就是“MVC”的意思是——但在实践中,它只是考虑不周的“规范数据模型”想法的重新实现。领域和表示是不同的关注点,因此,意味着不同的上下文模型 - 在后一种情况下,这是一个视图模型。
当我第一次开始做 MVC 工作时,我也不愿意使用视图模型。但当我更加习惯这个想法后,我意识到这确实是唯一可行的解决方案 - 特别是当您的“模型”主要是数据库本身的薄包装时。视图和数据以不同的方式和不同的速率变化;如果您不想担心不断出现的错误和回归,那么您需要在两者之间进行一些隔离。构建一个映射层并收工。
此时,我已经开始为每个视图创建不同的视图模型,无论我是否需要它。一开始,它可能只是模型类的复制品,但这意味着我可以随时以任何方式调整它,而不必修改底层模型 - 反之亦然。 正如电视所说,初始视图模型非常容易使用 AutoMapper 生成,可能会占用您 30 秒的时间。
只需使用视图模型,并希望最终该工具支持视图模型自动生成。
You've named three things here:
That third point is a trap; just because something is in your database, doesn't mean it's part of your domain model.
Navigation might be based on a database. It might also be be in a site map or hard-coded into the application. It's actually not application data, it's application configuration. If you're storing it in the application database, that's OK (well, not really), but it is not part of the model itself.
Similarly, site statistics usually are stored in a database, but they're stored in a different database, specifically an analytics database (and many people just "outsource" this to Google). So again, they are a kind of data, but they are not your model.
If you want your application to make sense, you need to separate these concerns at a conceptual level. Navigation gets done in your master page/layout, including whatever dynamic code is necessary to make it work. It is pure view logic - don't let it leak into your model. It's completely OK and usually preferable to use the ViewData/ViewBag for concerns that are ancillary to the actual feature that is currently in use.
Now, assuming there are other kinds of view data that actually are application data: It's true in principle that views are supposed to be connected directly to models - that is after all what "MVC" means - but in practice, it's just a re-implementation of the ill-conceived "canonical data model" idea. Domain and presentation are separate concerns, and as such, imply different contextual models - in the latter case, that's a View Model.
When I first started doing MVC work, I was reluctant to use view models as well. But after I became more accustomed to the idea, I realized that it was really the only tenable solution - especially when your "model" is mostly a thin wrapper over the database itself. Views and data change in different ways and at different rates; if you don't want to be worrying about a constant stream of bugs and regressions then you need some insulation between the two. Build a mapping layer and call it a day.
At this point I've taken to creating a different view model for every view, whether I think I need it or not. At the beginning, it might be nothing but a carbon copy of a model class, but it means I can tweak it at any time and in any manner without having to screw around with the underlying model - and vice versa. As tv says, the initial view model is trivially easy to generate with AutoMapper, and will take up maybe 30 seconds of your time.
Just use view models, and hope that eventually the tools support view-model auto-generation.
如果您创建用于编辑员工的页面,但还显示您提到的内容(站点统计信息/菜单),为什么不将它们放入部分视图或布局文件中?
If You create page for editing employee but You also display things You mentioned (site statistics/menus) why not put them in partial views or layout files?