Asp.net-mvc – Where to convert a DTO to ViewModel

asp.net-mvcdomain-driven-designdtoseparation-of-concernsviewmodel

I've inherited an MVC2 project using a pretty standard and decently well kept DDD pattern. I've been doing a lot of reading on the whole DTO/ViewModel debate as well.

Currently our DTOs are often used like ViewModels. It honestly doesn't make a difference for what we're doing but I'd like to use proper ViewModels as we upgrade the site.

Here's my question:

Our "domain" project's models currently hold the entities and return DTOs to my controllers. Now I need to map that DTO to a ViewModel. Where should I do this?

  • Right in the controller?
  • In the domain project?
  • Elsewhere?

I'm keeping my ViewModels alongside the views in our "Web" project so it feels wrong to convert DTO -> ViewModel in the domain project. It also feels wrong to do it in the controller.

What have others done?

Edit:

This question/answer suggests handling it in the controller. It sure gets easy to over think this.

Best Answer

DTOs are typically technology specific. For example in the .NET world your DTOs are likely decorated with DataContract and DataMember serialization attributes. Moreover, DTOs together with the service that returns them form an adapter to the domain in terms of a hexagonal architecture. They adapt your domain to a specific transport technology such as HTTP and as such they live outside of your domain. In other words, the domain shouldn't have knowledge of the DTOs - the DTOs should be defined in a separate project. The project containing the service should have mapping code which maps domain objects to DTOs.

An ASP.NET MVC project is similar in nature - it adapts your service/DTOs (or domain objects directly) to a presentation technology, HTML in particular. As such, the DTOs shouldn't be aware of ViewModels. Instead, the MVC controller should invoke the mapping between DTOs and ViewModels. This can be done in a variety of ways but what I've found to work best is a constructor in the ViewModel accepting a DTO. Also, in cases where a controller action warrants the creation of a DTO to be sent back to the service, the ViewModel can contain a method for creating the DTO based on the ViewModel. This contains all mapping code in the ViewModel closest to the actual data - an instance of the information expert pattern. Another way to implement this would be to use something like AutoMapper which uses convention based mapping to avoid boilerplate code. Anything beyond that I would consider overkill unless it is called for.

In many cases, your ViewModel ends up looking just like the DTO but with ASP.NET MVC specific attributes for binding and validation. Even though this may seem like a violation of DRY, these are really separate responsibilities.