在Asp.net MVC中,是否建议使用视图模型派生自领域模型?

10
我正在使用ASP.Net MVC,但这似乎是一个更通用的MVC问题。
假设您有一个表示人的领域模型,并且您有一个用于编辑个人信息的视图。在Person领域对象中包含了居住州(State of Residence)属性,在视图中你希望有一个下拉菜单来列出各州的名称。
创建一个从领域模型继承并且只包含UI所需属性的视图模型,有没有任何不推荐的理由?如果有,请说明原因。
感谢您。
4个回答

7

我认为从领域模型派生视图模型会引入MVC旨在避免的耦合; 但是,话虽如此,做出最符合您应用程序的决定。

我更喜欢将视图模型分开,因为这样可以使我自由地大幅更改领域模型,并获得改进的编译时支持,以将我的视图模型重新映射到新的领域模型。


3
“领域模型会引入耦合,而MVC旨在避免这种情况。” 这个说法完全不正确。在Django/RoR实现中,视图模型实际上是紧密耦合的数据库架构的表示形式。MVC并不对您的模型应该是什么有任何意见,只是它不属于您的V和C部分。” - John Farrell
@jfar:您的观点很有道理;然而,MVC自己的许多示例使用Linq-to-SQL或Linq-to-Entities或DataSets作为领域模型。所有这些模型都至少与持久存储机制有一定的耦合,并且在实践中经常被用作模型。 - kbrimington
@jfar:这里的问题不在于模型是否应该反映数据存储,而在于ViewModel是否应该继承模型。在我的应用程序中,出于我所描述的原因,它们并没有继承,尽管我采取了更加实用主义而非教条主义的方法。我不反对模型与数据结构耦合。我只是认为视图模型应该比模型更紧密地与视图耦合。 - kbrimington
@erg39:我认为这取决于情况。存储库模式越来越受欢迎,但它仍然很新,并且还有其他可行的方法,包括直接绑定到 Linq-to-SQL 模型。如果我要扩展 API 以供其他方使用和分发,我会发现存储库模式非常有用,但对于我的内部应用程序来说有点繁琐。 - kbrimington
@kbrimington:“这里的问题不在于模型是否应该反映数据存储”,我只是在回应答案。这个答案基于一个错误的陈述。 - John Farrell
显示剩余8条评论

7

1
我理解使用视图模型的用途,但即使你引用的链接得出结论:“如果在简单情况下能够直接绑定到领域模型,则这是最简单和最容易的解决方案。” 原帖中提到的场景几乎与领域模型中包含的内容相同(尽管我不否认如果它变得更加复杂可能会崩溃)。我理解许多人(大多数?)认为从CRUD领域模型派生视图模型并不理想。我只是不明白,如果使用领域模型最简单和最容易,为什么会这样。谢谢。 - erg39

2
不,你真的不想这样做。
使用ViewModel的主要原因是因为您的领域实体往往是庞大、复杂和与持久性机制紧密耦合的。当它们遇到DefaultModelBinder等问题时,往往会出现奇怪、有趣或破坏性的行为。
通过使用简单得多的ViewModel类,您可以避免大部分这些问题,同时进一步将UI层与领域模型解耦。
现在,您应该提供轻松的方法来生成ViewModel从领域实体或更新领域实体从ViewModel。

对于关于领域实体倾向于绑定持久化机制的评论,我表示赞同。我发现使用POCO作为视图模型时,我不太可能遇到奇怪的序列化行为。 - kbrimington
你能详细说明一下“你应该提供简单的方法从领域实体生成ViewModel或从ViewModel更新领域实体”这个评论吗?你是指通用的方法吗?我想尽可能避免编写大量针对每个ViewModel的实体更新代码,除非必要。 - erg39
你可以做许多事情来简化工作,例如使用AutoMapper,但是根据实体和视图模型相差的程度,你可能需要一些手动代码来维护。 - Wyatt Barnett

-1

我不同意这里的大部分建议。

我认为你的领域模型应该保持简洁,而视图模型应该只做必要的事情。 如果你的视图需要一个人和伦敦的时间,我不认为这样做有什么问题:

ExampleViewModel : Person {
 Public DateTime LondonTime { get; set;}
}

或者

AnotherViewModel 
{
 Public Person SomeGuy { get; set;}
 Public List<Kitty> Cats{ get; set;}
}

如果您的视图需要一个人和一列小猫,这样可以保持您的域整洁。伦敦的时间与一个人无关,但在您的视图中仍然需要获取数据。这就是视图模型的全部意义,我个人认为。

第一个例子应该优先使用组合而不是继承。 - mathieu

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