在何处将DTO转换为ViewModel?

Rya*_*ger 17 asp.net-mvc domain-driven-design dto separation-of-concerns viewmodel

我使用了一个非常标准且保存得很好的DDD模式继承了一个MVC2项目.我也在整个DTO/ViewModel辩论中做了很多阅读.

目前我们的DTO经常像ViewModels一样使用.它老实说并没有对我们正在做的事情产生影响,但我想在升级网站时使用正确的ViewModel.

这是我的问题:

我们的"域"项目模型目前拥有实体并将DTO返回给我的控制器.现在我需要将该DTO映射到ViewModel.我应该在哪里这样做?

  • 在控制器中?
  • 在域项目中?
  • 别处?

我将ViewModel与我们的"Web"项目中的视图保持在一起,因此在域项目中转换DTO - > ViewModel感觉不对.在控制器中执行此操作也感觉不对.

其他人做了什么?

编辑:

这个问题/答案建议在控制器中处理它.很容易想到这一点.

eul*_*rfx 16

DTO通常是特定于技术的.例如,在.NET世界中,您的DTO可能使用DataContractDataMember序列化属性进行修饰.此外,DTO与返回它们的服务一起构成了六角形体系结构的域适配器.它们使您的域适应特定的传输技术(如HTTP),因此它们位于您的域之外.换句话说,域名不应该了解DTO - DTO应该在单独的项目中定义.包含服务的项目应具有将域对象映射到DTO的映射代码.

一个ASP.NET MVC项目在本质上是相似的-它适应您的服务/ DTO的(或域直接对象)的演示技术,HTML尤其如此.因此,DTO不应该知道ViewModels.相反,MVC控制器应该调用DTO和ViewModel之间的映射.这可以通过多种方式完成,但我发现效果最好的是ViewModel中接受DTO的构造函数.此外,在控制器动作保证创建要发送回服务的DTO的情况下,ViewModel可以包含用于基于ViewModel创建DTO的方法.这包含最接近实际数据的ViewModel中的所有映射代码 - 信息专家模式的实例.实现这一点的另一种方法是使用类似AutoMapper的东西,它使用基于约定的映射来避免样板代码.除非有人要求,否则我会考虑过度杀伤.

在许多情况下,ViewModel最终看起来就像DTO,但具有ASP.NET MVC特定的绑定和验证属性.即使这看起来像是对DRY的违反,但这些都是不同的责任.

  • 恕我直言,如果它上面有"[DataMember]",那么它不是DTO. (4认同)

And*_*ess 6

首先,始终为您的视图使用显式ViewModel,不要将DTO一直传递到View.这是多一点的前期工作,但它可以让你更多的控制权究竟需要在查看哪些数据(这也可以防止像EF框架从侧面加载很多你可能会或可能不会使用额外的数据)

其次,本文概述了Orchestrator模式http://www.simple-talk.com/dotnet/asp.net/never-mind-the-controller,-here-is-the-orchestrator/,它可能只是另一个名称其他一些模式,但我喜欢这种格式.

实质上,您为每个Controller创建一个Orchestrator.Orchestrator接收数据(通常是ViewModel,以及所需的任何其他基本数据类型,特别是来自HttpContext的数据类型),并返回ViewModel(如果View需要,否则返回其他一些返回类型).

这种格式使您能够轻松地对实际逻辑进行单元测试,而无需尝试模拟控制器所需的HttpContext内容.