DTO = ViewModel?


102

我正在使用NHibernate持久化域对象。为简单起见,我将ASP.NET MVC项目用作表示层和服务层。

我想从控制器类中以XML返回我的域对象。在阅读了一些有关Stack Overflow的文章之后,我收集了DTO。但是,我也遇到过有关ViewModel的帖子。

我的问题:数据传输对象和ViewModel是同一件事吗?还是ViewModel是DTO的一种子模式?


9
我认为有必要提及一下,ASP.NET MVC中的ViewModels不是100%等同于WPF(MVVM)中的ViewModels,因为大多数答案都提到了MVVM,而您正在使用ASP.NET MVC。
Matthijs Wessels,

Answers:


104

DTO的规范定义是没有任何行为的对象的数据形状。

ViewModels是视图的模型。ViewModel通常是来自一个或多个对象(或DTO)以及特定于视图行为的任何其他成员(可由视图执行的方法,指示如何切换视图元素的属性等)的全部或部分数据。您可以将viewmodel视为视图的所有数据以及行为。ViewModel可能会也可能不会一对一映射到业务对象或DTO。

顺便说一句,如果某个视图模型需要来自持久对象的数据子集,则NHibernate 投影会派上用场。


您能否解释一下:“ DTO是没有任何行为的对象的数据形状”?
roozbeh S

2
含义... DTO类通常仅包含属性,并且不包含具有业务逻辑等的任何方法...
Daniel Auger

71

ASP.NET MVC实践中的ViewModel与DTO相同,但是MVVM模式中的ViewModel与DTO不同,因为MVVM中的ViewModel具有行为,但DTO没有。


4
这是一个很好的答案。尽管细节不足。
菲尔(Phil)

5
为什么ASP.NET MVC中的ViewModel应该与DTO相同?这是没有意义的。ViewModel可以具有DTO不能具有的行为。这不依赖于mvc。
伊丽莎白2013年

8
+1用于区分ASP.NET MVC ViewModel和MVVM ViewModel。
罗纳德

5
@Elisa-一个相当老的问题的答案是,在ASP.NET MVC中,视图在控制器(不是ViewModel)上调用Actions,以便以无状态方式更改Model和View。因此,形状为视图的DTO本质上与ViewModel相同。但是,在具有另一个序列化边界的较大系统中,如果将DTO与专门为View设计的ViewModel分开,则DTO可能是有益的。
丹桑2014年

27

DTO!=视图模型

MVVM模式中,ViewModel用于将模型与视图隔离。为了表示模型​​,您可以使用简单的DTO类,该类又通过NHibernate映射到数据库。但是我从未见过将其建模为DTO的ViewModel类。ViewModel类大多数具有行为,而DTO没有。


2
所以DTO可以只是结构(或者是应该模仿结构功能的类)?
Max Alexander

20

DTO-数据传输对象与它所说的完全一样,是用于传输数据的容器。他们没有行为,只有一堆setter和getter。有些人使它们不变,只是在需要时创建新的,而不是更新现有的。它们应该可序列化以允许跨线传输。

通常,DTO用于跨过程边界将数据从一层传送到另一层,因为对远程服务的调用可能很昂贵,因此所有必需的数据都被压入DTO并以一个块(粗粒度)传输到客户端。

但是,有些人使用屏幕绑定DTO的概念(与跨进程边界无关)。同样,这些数据将填充有所需的数据(通常是特定屏幕所需的数据,并且可能是来自各种来源的数据的集合)并发送给客户端。

http://blog.jpboodhoo.com/CommentView,guid,21fe23e7-e42c-48d8-8871-86e65bcc9a50.aspx

在已经说明过的简单情况下,此DTO可用于绑定到视图,但在更复杂的情况下,则需要创建ViewModel并将数据从DTO卸载到ViewModel,这显然是更多的工作(应用MVVM模式时) 。

再次如前所述,DTO!= ViewModel

DTO和ViewModel在生活中有不同的用途


13

首先,主要区别在于ViewModel可以具有DTO一定不能禁止的行为或方法!

其次,在ASP.NET MVC中将DTO用作ViewModel可以使您的应用程序与DTO紧密耦合,这与使用DTO恰恰相反。如果这样做,则使用域模型或DTO有什么区别,获得反模式的复杂性如何?

ASP.NET中的ViewModel也可以使用DataAnnotations进行验证。

相同的DTO可以具有不同的ViewModels映射,并且一个ViewModel可以由不同的DTO组成(总是具有对象映射而不是合成)。因为我认为如果您的ViewModel包含DTO甚至更糟,我们将遇到同样的问题。

在您的表示层中,将DTO视为合同,您将收到一个对象,您必须将其视为您的应用程序的陌生对象,并且对其没有任何控制权(即使您拥有服务,dto和表示层)是你的)。

最后,如果您进行这种干净的分离,显影剂可以轻松地协同工作。设计ViewModel,View和Controller的人不必担心服务层或DTO实现,因为他将在其他开发人员完成其实现时进行映射...他甚至可以使用Mocking工具或手动模拟来填充表示层包含要测试的数据。


1
我刚刚安装了VS 2012,并查看了MVC 4 Single Page Application。在示例项目中,DTO用作WebApi中控制器方法(或操作)的参数。换句话说,将JSON发布到这些方法,并使用MVC魔术,将数据自动传递到DTO,然后再传递给方法。您是否认为在这种情况下使用DTO是错误的?ViewModels是否应与Web API一起使用?我要求更好地理解,因为我还不是很熟悉这些概念。
让·弗朗索瓦·比彻姆

SalutJean-FrançoisBeauchamp :) ASP.NET MVC可以将url pram解析为一个对象,例如:假设我已将此映射映射到Index方法ajax / index / {jobID} / {ResultsToSkip} / {ResultsToSend}”,而不是在控件中的Index(int jobID,int ResultsToSkip,int ResultsToSend)中,我将拥有Index(request)(请求是封装3个字段jobID的对象...)所以现在,您正在使用参数而不是params讨论封装的对象DATA,所以我们可以说requestDTO。例如,您必须添加其他字段,您仅更改DTO,而不更改api接口方法
riadh gomri

9

对于一些简单的视图,我将使用DTO作为模型,但是随着视图变得越来越复杂,我将创建ViewModels。

对我来说,这是速度(使用DTO,因为我已经拥有了它们)和灵活性(创建ViewModels意味着更多的关注点分离)之间的平衡。


2
不错的实用答案。
西蒙·图西

0

如果将DTO用作ViewModel,则意味着由于某些原因要更改DTO,因此您对DTO的依赖性很高,那么这可能会影响ViewModel。

更好地使用DTO并转换为viewmodel。


-1

DTO当我们需要在单个视图中显示/使用多个模型数据/属性时,我们可以使用与Model类相同的模型,也可以使用viewmodel。示例:我首先使用实体​​框架数据库创建一些模型。因此,现在所有模型都基于数据库生成。现在我们需要数据注释,对于这些数据注释,我们可以创建一个文件夹名称DTO。在此DTO文件夹中,我们可以使所有已经生成的模型保持准确,并在属性上方添加数据注释。然后,我们可以使用此DTO类使用任何操作(使用controller,views)。当我们需要复杂的视图时,我的意思是当我们在一个视图中需要多个类数据时,可以使用viewmodel。对于viewmodel,我们可以创建一个文件夹名称viewmodel,然后创建一个自定义类并保留我们需要的属性。我试图清除自己。任何建议高度赞赏。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.