我们可以只使用 DTO 而不是视图模型吗?



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

并使用视图模型将数据传递到 MVC 中的视图

目前,我们有:

  1. DTO作为一个单独的项目
  2. ViewModel 位于 UI 项目中(另一个文件夹以及控制器)

在我们的案例中,我看到的唯一区别是DTO必须通过网络传递并作为JSON发送,而ViewModel必须在视图中传递才能呈现为HTML。

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

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

将它们分开

鲍勃曾经这样做过。他有一个网站,显示用户的个人资料,包括他们的姓名和电话号码。他还有一个 API 调用,允许客户端检索具有相同信息的相同配置文件。因此,他对网站的ViewModel和API的DTO使用相同的类。

起初一切都很好。事实上,公司发展得如此之好,以至于鲍勃能够出售他的股票期权并退休。软件工程部门在很大程度上被外包了,人们并没有真正相互交谈。

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

该公司上线了生产,用户名功能取得了成功。只有一个问题。所有 API 客户端现在都接收包含用户登录名、电子邮件地址和其他所有内容的 JSON,包括他们的哈希密码。

不要成为鲍勃。

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

  • Project.Web (MVC Application)
  • Project.DTO (Plain C# classes)
  • Project.API (Web API Application)

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

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

Project.Web <---> Project.API

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

关于保持视图模型和DTO分离的问题,我可以看到以下几点支持它:

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

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

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

我们使用DTO是因为它

  • 删除循环引用。

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

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

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

  • 避免"过度发布"漏洞。

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

所以基本上有什么区别

  • DTO用于传输数据
  • 视图模型用于向最终用户显示数据。

这个术语很简单,因为您的视图模型是经常更改(按需)的东西。

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

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

但是在您的 UI 层中,您只想显示客户的全名、性别以及计算的年龄。

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

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

查看更多

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

相关内容

  • 没有找到相关文章

最新更新