我们目前使用 DTO 进行 Web API 请求和响应
并使用视图模型将数据传递到 MVC 中的视图
目前,我们有:
- DTO作为一个单独的项目
- 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