哪一层应该构建一个View Model?

时间:2010-04-27 09:34:57

标签: asp.net-mvc viewmodel s#arp-architecture

我正在使用S#arp架构,我不记得我在哪里阅读它,但是他们说他们的ViewModel应该存储在服务层,你的视图应该将viewmodel提交给服务进行处理。

我的问题是这个。应该构建ViewModel的哪一层?它应该在服务层,控制器是否请求它?或者控制器应该自己构建它?还有一个关于更新视图模型的问题,就好像它包含集合,并且模型状态无效,您还需要重新填充任何列表。

有什么建议吗?

非常感谢

马特

5 个答案:

答案 0 :(得分:11)

根据传统方法或理论,ViewModel应该是User界面层的一部分。至少这个名字是这样说的。

但是当你开始使用Entity Framework,MVC,Repository等实现它时,你就会意识到其他的东西。

有人必须使用ViewModels(最后提到的DTO)映射实体模型。是应该在A)UI层(由Controller),还是在B)服务层?

中完成

我使用选项B.选项A是禁忌,因为几个实体模型组合在一起形成ViewModel的简单事实。我们可能不会将不必要的数据传递到UI层,而在选项B中,服务可以使用数据并在映射(到ViewModel)之后仅将所需/最小值传递给UI层。

但是,让我们假设我们使用选项A,我们将ViewModel放在UI层(以及服务层中的实体模型)。

如果服务层需要映射到ViewModel,则服务层需要访问UI层中的ViewModel。哪个图书馆/项目? Viewmodel应位于UI层中的单独项目中,此项目需要由Service Layer引用。如果ViewModel不在一个单独的项目中,那么就有循环引用,所以没有去。让服务层访问UI层看起来很尴尬,但我们仍然可以应对它。

但是,如果有另一个使用此服务的UI应用程序呢?如果有移动应用程序怎么办? ViewModel有多么不同?服务应该访问相同的视图模型项目吗?或者所有的UI项目都会竞争吗?

在考虑这些因素后,我的回答是将Viewmodel项目放在服务层中。每个UI层都必须访问服务层!并且可能有许多类似的ViewModel都可以使用(因此服务层的映射变得更容易)。这些天通过linq完成映射,这是另一个好处。

最后有关于DTO的讨论。还有关于ViewModels中的数据注释。具有数据注释的ViewModel不能驻留在服务层中。因此,DTO将是ViewModel的精确副本,并在两者之间进行一对一映射(例如使用AutoMapper)。 DTO仍然具有UI(或多个应用程序)所需的逻辑,并且驻留在服务层中。 UI层ViewModel只是从DTO复制数据,并添加了一些“行为”(例如:属性)。

虽然与问题没有直接关系。 'ViewModelFaçade'(另一个视图模型中的viewmodel)&必须注意channel 9 link中提到的'命令'也值得探索(@ 11:48开始)

答案 1 :(得分:8)

我在控制器中创建视图模型。控制器采用域实体(通过模型绑定器从数据库检索),可能在其他视图模型中,联系存储库以获取其他数据,创建新视图模型,并将其传递到适当的视图(或重定向)。因此,控制器的职责是根据输入域数据准备视图/视图模型(当然也处理错误)。

您可以查看here以替代在控制器中创建视图模型。此技术将视图模型创建移动到操作之外,因此不仅控制器操作接受纯域对象,而且它们还返回纯域对象。我不会说它在所有情况下都是合适的,但学习起来非常有趣。

上述与AutoMapper相关的技术也提出了类似于“我应该将视图模型传递给服务层”的问题。不,你没有。如果需要将复杂对象传递给服务或域层,则可以在相应的服务/域层中定义此对象,并使用它将数据传递到这些层。然后,可以轻松地将此对象映射到视图模型/从视图模型映射(例如,使用AutoMapper)。但是您的较低层(服务/域)不应该耦合到上层(视图/控制器)。不是在这种情况下,不在其他情况下。从来没有低级别的层应该依赖于它们上面定义的东西。

答案 2 :(得分:3)

这些文章可能对你很有意思:

DDD : Command Query Separation as an Architectural Concept

Better Application Services and CQS using S#arp Architecture

有一个与第二篇文章关联的示例应用程序,它在服务层中具有视图和表单模型,而不是控制器。

答案 3 :(得分:0)

另见Who Can Help Me - 太棒了。该框架基于S#arp架构。它有很多关于View / Form / Edit viewModels的指导。

答案 4 :(得分:0)

我实现了Wpf应用程序,但是在单独的层中实现ViewModel时遇到了问题。为什么?当我完成该应用程序时,他们还需要该应用程序的Web版本。然后,我还必须在该层中为Web实现另一个ViewModel。那感觉不对。解决方案?在Web和Wpf应用程序中实现ViewModels。让存储库返回一个实体。然后在Controller或Wpf中的Code-Behind中,将Entity的内容填充到ViewModel中。实体是数据转换对象(DTO)。它从ViewModel中的实体传输。 Pluralsignt的Blip Sample应用程序与此有关。

但是在Web或Wpf应用程序本身中实现ViewModels的最大理由是取决于View的类型。对于图层,您希望尽可能地独立。有了ViewModel,可以说该数据层取决于UI。 Web和Wpf的视图是不同的。 Web具有批注,Wpf具有NotifyProperty语句,因此应将其保留在所属位置。