Asp.net mvc 3 为什么有两个类,视图模型和域模型?

Asp.net mvc 3 为什么有两个类,视图模型和域模型?,asp.net-mvc-3,model,viewmodel,modelbinders,Asp.net Mvc 3,Model,Viewmodel,Modelbinders,我知道使用域模型作为视图模型可能不好。如果我的域模型有一个名为IsAdmin的属性,并且我有一个Create controller操作来创建用户,那么有人可以修改我的表单并让它发布IsAdmin=true表单值,即使我没有在视图中公开这样的文本字段。如果我使用模型绑定,那么当我提交我的域模型时,那个人现在将是管理员。因此,解决方案变成只公开视图模型中需要的属性,并使用AutoMapper之类的工具将返回的视图模型对象的属性值映射到域模型对象的属性值。但是我读到类的bind属性可以用来指示模型绑定

我知道使用域模型作为视图模型可能不好。如果我的域模型有一个名为IsAdmin的属性,并且我有一个Create controller操作来创建用户,那么有人可以修改我的表单并让它发布IsAdmin=true表单值,即使我没有在视图中公开这样的文本字段。如果我使用模型绑定,那么当我提交我的域模型时,那个人现在将是管理员。因此,解决方案变成只公开视图模型中需要的属性,并使用AutoMapper之类的工具将返回的视图模型对象的属性值映射到域模型对象的属性值。但是我读到类的bind属性可以用来指示模型绑定器应该绑定和不应该绑定哪些属性。那么,创建两个独立的类(域模型和视图模型)的真正原因是什么呢?这两个类本质上代表相同的东西,然后在映射它们时产生开销?这更像是一个代码组织问题吗?如果是,我将如何受益

编辑


对于独立于域模型的视图模型,我遇到的最重要的原因之一是需要实现MVVM模式(基于Martin Fowler的PM模式)来管理复杂的UI

我发现,虽然我的域模型让我获得了85%的所需字段,但它从来没有覆盖我在视图中所需的100%的值。特别是当涉及到权限以及用户是否应该访问视图的某些部分时


我试图遵循的设计理念是在我的视图中尽可能少地包含逻辑。这意味着我的视图模型中有“CanViewThisField”或“CanEditThisField”等字段。当我第一次开始使用MVC时,我会将我的域模型作为我的视图模型,并且我总是遇到这样的情况,即我只需要一个或两个以上的字段来减少视图的混乱。从那以后,我走上了这条路,它对我来说非常有效。我不再与我的代码作斗争,但我能够在不影响域模型的情况下增强我的视图模型。

有时需要以特定的方式显示数据(即,以mm/dd/yyyy与yyyy/mm/dd格式显示日期),通常在视图中而不是在域模型中更容易创建此属性,您将(或应该)在数据库中拥有一个到列的映射。

拥有ViewModel的另一个很好的理由是分页大数据集。您可以向视图传递一个Person数组(
Person[]
),但诸如页数、当前页面数、页面大小等元数据不属于
Person


因此,PersonListViewModel可以解决这个问题。

ViewModel只包含视图所需的成员。它们通常可以被认为是底层领域模型的简化或“扁平化”

你可以这样想:

  • 视图模型:这是适合在此模型上渲染的数据 看法
  • 域模型:这是我的应用程序所需的全部信息 关于此实体以执行其所有功能
例如,我的订单类有一个名为Customer的成员,它是一个关联,也就是说,我的订单有一个Customer。此客户对象具有成员,如Firstname、Lastname等。。。但是,我如何在订单的“详细信息”视图或订单列表以及下订单的客户上显示这些信息呢

好的,使用ViewModel我可以有一个OrderListItemViewModel,它有一个CustomerName成员,我可以将Firstname和Lastname的组合从Customer对象映射到这个对象。这可以手动完成,或者最好使用或类似的方法

使用这种方法,您可以拥有多个特定于不同视图的订单视图模型,例如,“订单列表”视图可能会以与“订单详细信息”视图不同的方式呈现客户名称

ViewModels的另一个优点是,您可以减少视图中底层域对象不需要的额外数据,例如,如果我正在查看订单列表,我真的想查看所有客户的联系信息、账单详细信息等吗。。。?我想这取决于列表的目的,但可能不是。

你需要记住 您的
域模型类仅在
内部使用
;也就是说,它们永远不会被送到

客户这就是您的服务模型类型(视图模型类型)的用途,因为它们表示将在客户端和您的服务之间来回传递的数据。

也检查这个问题谢谢,这很有意义。但是,我们不能在域模型上创建函数来实现这一点吗?比如DisplayAddress(),它将结合地址、城市、州和邮政编码等域属性?db只映射属性,不映射函数。这个想法违反了一些设计理念吗?在某种程度上,是的。如果您真的愿意,您可以在域模型中完成所有这一切,并且它的工作方式也一样。然而,我从来没有看到过在维护过程中它工作得很好。通常,我看到过将这些类型的内容放入视图模型(或您正在使用的任何表示模型)中。因此,实际上,这只是一个组织问题,而不是任何问题。:)我同意减少视图的混乱,但是我们不能将这种类型的功能抽象到域模型而不是视图模型吗?我之前说过,但是我不能在我的域模型上使用DisplayAddress()函数,它可以组合域属性,比如地址、城市、州和邮政编码吗?db只映射属性而不映射函数。显然,任何事情都是可能的,这取决于你想走哪条路。我已经为我生成了我的域模型,所以我并没有真正接触那个代码。如果您正在使用任何类型的ORM,那么情况就是这样。视图模型在不影响性能的情况下为我提供了最大的灵活性