Asp.net mvc 服务层是否应该返回MVC应用程序的视图模型?

Asp.net mvc 服务层是否应该返回MVC应用程序的视图模型?,asp.net-mvc,service-layer,asp.net-mvc-viewmodel,Asp.net Mvc,Service Layer,Asp.net Mvc Viewmodel,假设您有一个ASP.NET MVC项目,并且正在使用服务层,例如ASP.NET网站上的本联系人管理器教程: 如果视图中有viewmodels,服务层是否是提供每个viewmodel的适当位置?例如,在服务层代码示例中有一个方法 public IEnumerable<Contact> ListContacts() { return _repository.ListContacts(); } public IEnumerable ListCont

假设您有一个ASP.NET MVC项目,并且正在使用服务层,例如ASP.NET网站上的本联系人管理器教程:

如果视图中有viewmodels,服务层是否是提供每个viewmodel的适当位置?例如,在服务层代码示例中有一个方法

    public IEnumerable<Contact> ListContacts()
    {
        return _repository.ListContacts();
    }
public IEnumerable ListContacts()
{
返回_repository.ListContacts();
}
如果您想要一个IEnumerable,它应该放在服务层中,还是放在其他“正确”的地方


也许更合适的是,如果每个与ContactController关联的视图都有一个单独的viewmodel,那么ContactManagerService是否应该有一个单独的方法来返回每个viewmodel?如果服务层不是合适的地方,VIEWMDES对象应该在哪里被控制器使用?

< P>我想这取决于你认为的“服务”是什么。我从来没有真正喜欢过在单个类的上下文中使用术语服务;这是难以置信的模糊,并没有告诉你很多关于课程的实际目的

如果“服务层”是物理层,比如web服务,那么绝对不是;SOA上下文中的服务应该公开域/业务操作,而不是数据和表示逻辑。但是,如果服务只是作为一个抽象概念用于更高级别的封装,我看不出以您描述的方式使用它有任何问题


不要混淆概念。如果您的服务涉及视图模型,那么它应该是一个表示服务,并在实际模型之上分层,永远不要直接触及数据库或任何业务逻辑。

不,我不这么认为。服务应该只关心问题域,而不关心呈现结果的视图。返回值应该用域对象而不是视图来表示。

一般来说,不是

视图模型旨在向视图和从视图提供信息,并且应该特定于应用程序,而不是一般领域。控制器应协调与存储库、服务(我在这里对服务的定义做一些假设)等的交互,并处理视图模型的构建和验证,还应包含确定要呈现的视图的逻辑


通过将视图模型泄漏到“服务”层,您正在模糊您的层,并且现在可能会有特定于应用程序和表示的内容与域级别职责的内容混合在一起。

按照传统方法或理论,视图模型应该是用户界面层的一部分。至少名字是这么说的

但是,当您着手使用实体框架、MVC、存储库等来实现它时,您会意识到其他一些东西

必须有人将实体/DB模型映射到ViewModels(最后提到的DTO)。这应该在[A]UI层(由控制器)还是[B]服务层中完成

我选择选项B。选项A是否定的,因为几个实体模型组合在一起形成了一个ViewModel。我们可能不会将不必要的数据传递给UI层,而在选项B中,服务可以处理数据,并在映射(到ViewModel)后仅将所需/最小值传递给UI层

但是,让我们继续使用选项A,将ViewModel放在UI层(实体模型放在服务层)

如果服务层需要映射到ViewModel,那么服务层需要访问UI层中的ViewModel。哪个图书馆/项目?Viewmodel应该位于UI层的一个单独的项目中,该项目需要由服务层引用。如果ViewModel不在单独的项目中,则存在循环引用,因此无法使用。让服务层访问UI层看起来很尴尬,但我们仍然可以处理它

但是,如果有另一个UI应用程序使用此服务呢?如果有移动应用呢?ViewModel可以有多大的不同?服务是否应该访问相同的视图模型项目?所有UI项目是访问同一个ViewModel项目还是有自己的项目

考虑这些因素后,我的答案是将Viewmodel项目放在服务层中。每个UI层都必须以任何方式访问服务层!而且可能有很多相似的视图模型,它们都可以使用(因此映射对于服务层来说变得更容易)。如今,映射是通过linq完成的,这是另一个优点

最后,是关于DTO的讨论。以及ViewModels中的数据注释。带有数据批注(Microsoft.Web.Mvc.DataAnnotations.dll)的ViewModels不能驻留在服务层,而是驻留在UI层(但ComponentModel.DataAnnotations.dll可以驻留在服务层)。如果所有项目都在一个解决方案(.sln)中,则将其放在哪一层并不重要。在企业应用程序中,每个层都有自己的解决方案

所以DTO实际上是一个ViewModel,因为二者之间通常会有一对一的映射(比如使用AutoMapper)。同样,DTO仍然具有UI(或多个应用程序)所需的逻辑,并且驻留在服务层中。UI层视图模型(如果我们使用Microsoft.Web.Mvc.DataAnnotations.dll)只是从DTO复制数据,并添加一些“行为”属性

[现在这场讨论将有一个有趣的转折点,阅读…:I]

而且不要认为数据注释属性只适用于UI。如果使用System.ComponentModel.DataAnnotations.dll限制验证 然后,同样的ViewModel也可以用于前端和后端验证(从而删除驻留在DTO中的UI ViewModel副本)。此外,属性也可用于实体模型中。例如:使用.tt,可以使用验证属性自动生成实体框架数据模型,以便在发送到后端之前执行一些数据库验证,如max length。这节省了从UI到后端的往返验证。它还支持后端到re-v