我对使用ViewModel相当新,我想知道,ViewModel是否可以将域模型的实例包含为属性,或者这些域模型的属性是否应该是ViewModel本身的属性?例如,如果我有一个班级Album.cs
public class Album { public int AlbumId { get; set; } public string Title { get; set; } public string Price { get; set; } public virtual Genre Genre { get; set; } public virtual Artist Artist { get; set; } }
您是否通常让ViewModel保存Album.cs
该类的实例,或者您是否让ViewModel具有每个Album.cs
类属性的属性.
public class AlbumViewModel { public Album Album { get; set; } public IEnumerableGenres { get; set; } public IEnumerable Artists { get; set; } public int Rating { get; set; } // other properties specific to the View } public class AlbumViewModel { public int AlbumId { get; set; } public string Title { get; set; } public string Price { get; set; } public IEnumerable Genres { get; set; } public IEnumerable Artists { get; set; } public int Rating { get; set; } // other properties specific to the View }
Stefan.. 40
最有趣的部分:这不局限于@Html.EditorFor
在Id
,它实际上是"美好的旧数据/业务/ UI层",即关注点分离的分离-的问题.我稍后会说明这一点,但是现在; 请记住,它也适用于hidden
任何其他设计模式.
ViewModel是否可以包含域模型的实例?
基本上不是,虽然我看到它发生了很多.这取决于Id
你的项目的水平.
让我举个例子.想象一下以下视图模型:
public class FooViewModel { public string Name {get;set;} } public class DomainModel { public string Name {get;set;} }
和以下 automapper
public void Method1(FooViewModel input) { //duplicate code: same mapping twice, see Method2 var domainModel = new DomainModel { Name = input.Name }; //logic } public void Method2(FooViewModel input) { //duplicate code: same mapping twice, see Method1 var domainModel = new DomainModel { Name = input.Name }; //logic }
因此,在控制器的某个位置填充FooViewModel并将其传递给您的视图.
现在,请考虑以下方案:
1)域模型发生变化.
在这种情况下,您可能还需要调整视图,这在关注点分离的背景下是不好的做法.
如果已将ViewModel与DomainModel分开,则对映射(ViewModel => DomainModel(和back))进行微调就足够了.
2)DomainClass具有嵌套属性,您的视图只显示Foo.FooProp
.
我在实际场景中看到过这个问题.
在这种情况下,常见的问题是使用OtherFoo.FooProp
将导致嵌套对象的输入.这可能包括viewmodel
s和其他敏感信息.按照本课程,您将发现自己创建domainmodels
输入.如果将它与服务器端模型绑定或者自动化结合起来DTO's
,使用像firebug这样的工具来阻止对隐藏文件的操作是非常困难的.
虽然阻止其中一些字段可能很容易,但是你拥有的域/数据对象越多,保护这部分就越复杂.请记住,您可能希望更改您的DomainModel,原因不一定是针对视图.因此,对于DomainModel中的每次更改,您都应该意识到它可能会影响控制器的视图和安全性方面.
3)在asp.net-MVC中,通常使用验证属性.
您真的希望您的域包含有关您的观点的元数据吗?或者将视图逻辑应用于数据层?您的视图验证是否始终与域验证相同?它是否具有相同的验证逻辑?您使用的是域模型交叉应用程序吗?等等
我认为这显然不是采取的路线.
4)更多
我可以给你更多的场景,但这只是一个品味更具吸引力的问题.我只希望在这一点上你能得到点:)尽管如此,我答应了一个例子:
现在,真的很脏,domainmodels
它会起作用,但我不认为你应该想要它.
构建视图模型只需要多一点努力,通常与域模型类似,为80 +%.这可能感觉就像做了不必要的映射,但是当出现第一个概念差异时,你会发现它值得努力:)
因此,作为替代方案,我建议对一般情况进行以下设置:
创建一个viewmodel
创建一个域名模型
创建一个数据模型
使用库domainlayer
来创建从一个到另一个的映射(这将有助于映射logic
到domainmodels
)
好处是,例如; 如果在其中一个数据库表中创建一个额外的字段,它将不会影响您的视图.它可能会触及您的业务层或映射,但它会停止.当然,大多数时候你也想改变你的观点,但在这种情况下你不需要.因此,它将问题隔离在代码的一部分中.
web api/data-layer
另一个具体示例说明了它在Web-API/EF场景中的工作原理:
注意
正如@mrjoltcola所说:还有一个过于引擎的组件要记住.如果上述情况不适用,并且用户/程序员可以信任,那么你的好处就是去.但请记住,由于DomainModel/ViewModel混合,可维护性和可重用性会降低.