MVC/MVVM中的ViewModels /分层 - 最佳实践?

 书友32976730 发布于 2023-01-15 11:46

我对使用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 IEnumerable Genres { 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.EditorForId,它实际上是"美好的旧数据/业务/ 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将导致嵌套对象的输入.这可能包括viewmodels和其他敏感信息.按照本课程,您将发现自己创建domainmodels输入.如果将它与服务器端模型绑定或者自动化结合起来DTO's,使用像firebug这样的工具来阻止对隐藏文件的操作是非常困难的.

虽然阻止其中一些字段可能很容易,但是你拥有的域/数据对象越多,保护这部分就越复杂.请记住,您可能希望更改您的DomainModel,原因不一定是针对视图.因此,对于DomainModel中的每次更改,您都应该意识到它可能会影响控制器的视图和安全性方面.

3)在asp.net-MVC中,通常使用验证属性.

您真的希望您的域包含有关您的观点的元数据吗?或者将视图逻辑应用于数据层?您的视图验证是否始终与域验证相同?它是否具有相同的验证逻辑?您使用的是域模型交叉应用程序吗?等等

我认为这显然不是采取的路线.

4)更多

我可以给你更多的场景,但这只是一个品味更具吸引力的问题.我只希望在这一点上你能得到点:)尽管如此,我答应了一个例子:

Scematic

现在,真的很脏,domainmodels它会起作用,但我不认为你应该想要它.

构建视图模型只需要多一点努力,通常与域模型类似,为80 +%.这可能感觉就像做了不必要的映射,但是当出现第一个概念差异时,你会发现它值得努力:)

因此,作为替代方案,我建议对一般情况进行以下设置:

创建一个viewmodel

创建一个域名模型

创建一个数据模型

使用库domainlayer来创建从一个到另一个的映射(这将有助于映射logicdomainmodels)

好处是,例如; 如果在其中一个数据库表中创建一个额外的字段,它将不会影响您的视图.它可能会触及您的业务层或映射,但它会停止.当然,大多数时候你也想改变你的观点,但在这种情况下你不需要.因此,它将问题隔离在代码的一部分中.

web api/data-layer

另一个具体示例说明了它在Web-API/EF场景中的工作原理:

Web Api Datalayer EF

注意

正如@mrjoltcola所说:还有一个过于引擎的组件要记住.如果上述情况不适用,并且用户/程序员可以信任,那么你的好处就是去.但请记住,由于DomainModel/ViewModel混合,可维护性和可重用性会降低.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有