我们可以只使用DTO而不是ViewModel吗?

时间:2018-05-29 05:30:35

标签: c# asp.net-mvc viewmodel dto asp.net-mvc-viewmodel

我们目前使用DTO进行Web API请求和响应

并使用ViewModel将数据传递给MVC中的View

目前,我们有:

  1. DTO作为一个单独的项目
  2. ViewModel位于UI项目内(与控制器一起的另一个文件夹)
  3. 在我们的案例中,唯一不同的是DTO必须通过网络传递并作为JSON发送,而ViewModel必须在视图内传递以呈现为HTML。

    我们应该为MVC应用程序和我们的App /其他客户端保留单独的传输对象,还是仅通过DTO执行这两项工作,即将DTO传递给View而不是ViewModel?它有什么可能的缺点?

    我阅读了很多回复here但是没有示例和令人信服的理由在我们的案例中保留单独的ViewModel和DTO。

3 个答案:

答案 0 :(得分:6)

将它们分开

鲍勃做了一次。他有一个网站,显示用户的个人资料,包括他们的姓名和电话号码。他还有一个API调用,允许客户端使用相同的信息检索相同的配置文件。所以他为网站的ViewModel和API的DTO使用了相同的类。

一开始一切都很顺利。事实上,业务增长良好,鲍勃能够出售他的股票期权并退休。软件工程部门在很大程度上外包,人们并没有真正相互交谈。

一年后,产品所有者在响应客户请求时添加了一项要求,即配置文件页面不仅显示用户的名字和姓氏,还显示用户名和电子邮件地址。开发人员通过向ViewModel添加Login成员并使用AutoMapper填充它来完成任务并实现它。他认为ViewModel是服务器端代码,并没有考虑太多。

该公司推出了现场直播,用户名功能取得了成功。只有一个问题。所有API客户端现在都在接收包含用户登录名,电子邮件地址以及其他所有内容的JSON,包括其哈希密码。

不要成为鲍勃。

答案 1 :(得分:3)

我可以在这个模式中分享我的经验,因为我已经在项目中实现了它。将项目视为具有分布式体系结构的简单CRUD应用程序,并分为三个解决方案:

  
      
  • Project.Web(MVC Application)
  •   
  • Project.DTO(普通C#类)
  •   
  • Project.API(Web API应用程序)
  •   

Project.Web包含应用程序的UI逻辑,并依赖于Project.API进行所有CRUD操作,因为数据库相关操作是在Project.API中执行的。

现在是Project.DTO,它包含普通的C#类,用于来回传输数据。

  

Project.Web< ---> Project.API

为了使其更具分布性,我创建了Project.DTO作为Nuget包并将其托管在Artifactory中(您可以使用Nuget或任何其他存储库)并使用Nuget Package Manager来使用它。这种方法的主要优点是DTO类总是版本化且易于使用。

关于保持View Model和DTO分离的问题,我可以看到以下几点支持它:

  • 从API到Web的数据传输,反之亦然:它可能庞大而复杂。我说吧 应用程序想要创建一个客户端并将其所有细节添加到客户端 客户端地址,客户端通信,客户端历史等数据库 在Project.Web中,我们可以有其他细节,例如Session 相关数据,不需要传输的UI特定数据 从Web到API。因此,创建一个单独的DTO是有道理的 只传输Web和API常见的数据 独立于项目。
  • 对API或Web的传入请求:假设我已经创建了一个移动应用程序并准备好使用Project.API。如果我没有创建单独的View Model和DTO,我应该将我的ViewModel暴露给客户端(移动应用程序),这是不可取的,因为它可能包含应该保密的敏感字段。
  • 关注点分离:保持您的DTO仅传递数据,并且对于应用程序中的任何其他进程,请使用ViewModels。保持关注分离原则。

这些是我能想到的与你的问题相关的几点。

答案 2 :(得分:2)

两者都是具体的类,看起来一样,但它们的行为和目的是不同的。

我们使用DTO因为它

  • 删除循环引用。

  • 隐藏客户端不应查看的特定属性。

  • 省略一些属性以减少有效负载大小。

  • 展平包含嵌套对象的对象图,使客户端更方便。

  • 避免“过度发布”漏洞。

  • 将服务层与数据库层分离。

基本上差异是什么

  
      
  • DTO用于传输数据
  •   
  • ViewModels用于向最终用户显示数据。
  •   

这个术语很简单,因为ViewModel经常变化(按需)。

假设您有CustomerTable (FirstName, LastName, Age, Gender, DOB)

您将使用上述所有属性制作DTO。现在,如果在一个或多个图层中使用此DTO,您只需将其引用到这些图层即可。

但是在您的UI图层中,您只想显示客户的FullName,Gender以及Age Calculated。

您将使用最小化数据创建ViewModel CustomerViewModel(FullName,Gender, Age),以便将来频繁更改的可能性。

  • FullName - 来自DTO的FirstName + LastName
  • 性别 - 来自DTO的性别
  • 年龄 - 从DTO计算

查看更多

https://docs.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5