我们可以仅使用DTO代替ViewModel吗?

Sah*_*rma 3 c# asp.net-mvc dto viewmodel asp.net-mvc-viewmodel

我们目前将DTO用于Web API请求和响应

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

目前,我们有:

  1. DTO作为单独的项目
  2. ViewModel在UI项目中(与Controllers一起的另一个文件夹)

在我们的案例中,我看到的唯一区别是DTO必须通过导线传递并以JSON形式发送,而ViewModel必须在视图内部传递以呈现为HTML。

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

在这里阅读了许多回复但是在我们的案例中,没有示例,也没有令人信服的理由将ViewModel和DTO分开。

Joh*_* Wu 7

分开放置

鲍勃做了一次。他有一个网站,其中显示了用户的个人资料,以及他们的姓名和电话号码。而且他还进行了API调用,该调用使客户端可以使用相同的信息检索相同的配置文件。因此,他为网站的ViewModel和API的DTO使用了相同的类。

起初一切都很好。实际上,业务发展如此之好,以至于Bob能够出售其股票期权并退休。软件工程部门很大程度上已外包,人们之间并没有真正交谈。

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

该公司正式投入生产,用户名功能非常成功。只有一个问题。现在所有的API客户端都接收到JSON,其中包含用户的登录名,电子邮件地址以及其他所有信息,包括其哈希密码。

不要成为鲍勃。


iSa*_*rma 5

我可以分享我在项目中实施这种模式的经验。将该项目视为一个简单的分布式架构的CRUD应用,分为三个方案:

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

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

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

Project.Web <---> Project.API

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

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

  • 从 API 到 Web 的数据传输,反之亦然:它可能很大而且很复杂。假设我的应用程序想要创建一个客户端并将其所有详细信息添加到数据库中,例如客户端地址、客户端通信、客户端历史记录等。在 Project.Web 中,我们可以拥有其他详细信息,例如会话相关数据、需要的 UI 特定数据不需要从 Web 传输到 API。因此,创建一个单独的 DTO 是有意义的,只传输 Web 和 API 通用的并且独立于项目的数据。
  • 对 API 或 Web 的传入请求:假设我已经创建了一个移动应用程序并准备使用 Project.API。如果我没有创建单独的视图模型和 DTO,我应该将我的视图模型公开给客户端(移动应用程序),这是不可取的,因为它可能包含应该保密的敏感字段。
  • 关注点分离:保持 DTO 仅用于传递数据,对于应用程序中的任何其他进程,请使用 ViewModel。保持关注点分离原则。

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


Man*_*noz 5

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

我们使用 DTO 因为它

  • 删除循环引用。

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

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

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

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

  • 将服务层与数据库层解耦。

那么基本上有什么区别

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

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

假设你有一个CustomerTable (FirstName, LastName, Age, Gender, DOB)

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

但在您的 UI 层中,您只想显示客户的 FullName 、 Gender 以及计算出的年龄。

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

  • 全名 - 来自 DTO 的名字 + 姓氏
  • 性别 - DTO 中的性别
  • 年龄 - 根据 DTO 计算

查看更多

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