我知道将域模型用作视图模型可能会很糟糕。如果我的域模型有一个名为IsAdmin的属性并且我有一个Create控制器操作来创建用户,那么即使我没有在我的视图中公开这样的文本字段,也有人可以改变我的表单并使其发布一个IsAdmin = true表单值。 。如果我正在使用模型绑定,那么当我提交我的域模型时,该人现在将成为管理员。因此,解决方案只是在视图模型中公开我需要的属性,并使用AutoMapper之类的工具将我返回的视图模型对象的属性值映射到我的域模型对象的属性值。但是我读到类上的bind属性可以用来指示Model Binder它应该和不应该绑定哪些属性。那么究竟是什么原因使得两个独立的类(领域模型和视图模型)必须代表相同的东西,然后在映射它们时增加开销呢?这是一个代码组织问题,如果是,我如何受益?
修改
我遇到的一个与域模型分离的视图模型的最重要原因之一是需要实现MVVM模式(基于Martin Fowler的PM模式)来管理复杂的UI。
答案 0 :(得分:19)
我发现,虽然我的域名模型让我获得了我想要的字段的85%,但它从未覆盖我想要的100%的值。特别是涉及权限以及用户是否应该访问视图的某些部分时。
我试图遵循的设计理念是尽可能在我的视图中使用逻辑。这意味着我的视图模型中有字段,如“CanViewThisField”或“CanEditThisField”。当我第一次开始使用MVC时,我会将我的域模型作为我的视图模型,并且我总是遇到我只需要一两个字段的场景,以使我的视图不那么杂乱。我已经走了View Model/Model Builder路线,它对我来说非常有效。我不再对我的代码进行战斗,但能够在不影响域模型的情况下增强我的视图模型。
答案 1 :(得分:16)
拥有ViewModel的另一个好理由是分页大量数据。您可以将视图传递给Person(Person[]
)数组,但是元数据(例如页数,当前页面的数量,页面大小)不属于Person
类。< / p>
因此PersonListViewModel可以解决这个问题。
答案 2 :(得分:3)
ViewModel仅包含View所需的成员。它们通常可以被认为是对底层域模型的简化或“扁平化”。
像这样想一想:
例如,我的Order类有一个名为Customer的成员,它是一个composition关联,也就是说,我的订单有一个客户。此Customer对象具有Firstname,Lastname等成员...但是如何在订单的“详细信息”视图或订单列表以及放置它们的客户中显示此信息?
好吧,使用ViewModel我可以拥有一个具有CustomerName成员的OrderListItemViewModel,我可以将Customer对象的Firstname和Lastname的组合映射到此。这可以手动完成,或者更好地使用Automapper或类似的方式完成。
使用此方法,您可以拥有多个特定于不同视图的Order ViewModel,例如订单列表视图可能以与订单详细信息视图不同的方式呈现客户名称。
ViewModels的另一个优点是,您可以减少视图上基础域对象不需要的无关数据,例如:如果我查看订单列表,我真的想看到所有客户的联系信息,账单明细等等吗?我想这取决于列表的目的,但可能不是。
答案 3 :(得分:2)
有时您需要以特定方式显示数据(即以mm / dd / yyyy与yyyy / mm / dd格式显示日期)并且通常更容易在视图中创建此属性而不是在域模型中,您将(或应该)具有到数据库中列的映射。
答案 4 :(得分:2)
你需要记住
您的 domain model classes
仅使用internally
;也就是说,他们永远不会被发送到
客户。这就是您的服务模型类型(查看模型类型)的用途 - 它们代表将在客户端和您的服务之间来回传递的数据。