21

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.

Community
  • 1
  • 1
Ryan Bosinger
  • 1,832
  • 2
  • 16
  • 25
  • What do you mean DTO in here? is this your domain model? – cuongle Aug 09 '12 at 09:22
  • 3
    @CuongLe for me: DTO == "Data Transfer Object" in the fashion that most people discuss DTOs in the realm of .NET/Java and DDD. I'm still learning all of this so I don't know what else to say! – Ryan Bosinger Aug 09 '12 at 15:12
  • I still got confusion, I imply DTO that you mention is DOMAIN ENTITY? because DTO itself is "Data Transfer Object" working in Distribution layer. DTO and View Model is kind of the same level, if you work in service the top model called DTO, if you work in application, top model call View Model – cuongle Aug 09 '12 at 15:29

4 Answers4

19

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.

silkfire
  • 24,585
  • 15
  • 82
  • 105
eulerfx
  • 36,769
  • 7
  • 61
  • 83
  • 4
    IMHO, if it has `[DataMember]` on it, then it's not a DTO. – John Saunders Aug 09 '12 at 00:44
  • 1
    Why not? It seems like these attributes are there to support serialization which in turn supports data transfer, hence DTO. – eulerfx Aug 09 '12 at 01:30
  • Data Transfer Objects, as defined by Fowler, are meant to do nothing more than move data from one layer to another. "move data" doesn't mean support every possible mechanism for moving data, hence, I would exclude serialization as permitted under the definition of "DTO". I might call that a "DTO with support for serialization", maybe. – John Saunders Aug 09 '12 at 01:32
  • What other term would you use to describe those types of objects? – eulerfx Aug 09 '12 at 01:37
  • 1
    It depends on the reason for the attributes. If they are there because they are auto-generated, then my answer is, "don't". Visual Studio does some things for us because Microsoft wants more "ease of use", not because they're a good idea in general. – John Saunders Aug 09 '12 at 01:40
  • 1
    I've read again and again that part of the point of DTOs is that they be easy to serialize so I think I'm ok with the serialization attributes. There are a lot of great answers here but this seems like a good sum of everything I've been learning. I'll accept this. – Ryan Bosinger Aug 09 '12 at 15:08
6

First, always use explicit ViewModels for your Views, don't pass DTOs all the way up to the View. It's a bit more upfront work, but it gives you more control over exactly what data is needed in the View (it also prevents a framework like EF from sideloading lots of extra data you may or may not use)

Second, this article outlines the Orchestrator pattern http://www.simple-talk.com/dotnet/asp.net/never-mind-the-controller,-here-is-the-orchestrator/ which is probably just another name for some other pattern, but I like the format.

Essentially, you create an Orchestrator for every Controller. The Orchestrator takes in data (typically a ViewModel, and any other basic data types needed, particularly those from the HttpContext), and returns a ViewModel (if needed for the View, otherwise some other return type).

This format gives you the benefit of being able to easily unit test the actual logic without having to try to mock the HttpContext stuff that the Controllers need.

Andrew Burgess
  • 5,300
  • 5
  • 30
  • 37
  • 1
    That's pretty cool Andrew. This is the first time I've heard of the Orchestrator pattern and I'm really trying to figure out how _most_ people are architecting their apps. I'm going to check out this article though and maybe it'll open up some new thoughts. – Ryan Bosinger Aug 09 '12 at 15:14
  • In my App, I use Domain and Application Services. What is a difference between Orchestrator and App Service???? – zolty13 Oct 09 '18 at 10:07
4

Sounds like something you want to be doing in a purpose built mapping class/module.

I'd personally give my controller a dependency on a mapping service and then delegate the actual conversion to that before returning the view with newly-mapped viewmodel.

public class DemoController : Controller
{
    private readonly IMappingService _mappingService;

    public DemoController(IMappingService mappingService)
    {
        _mappingService = mappingService;
    }

    public ActionResult Stuff()
    {
        var vm = _mappingService.Map(yourDto);

        return View(vm);
    }
}
Greg Smith
  • 2,449
  • 2
  • 24
  • 37
2

A nice approach is to overload the constructor on your ViewModel with a second constructor which has the dto as a parameter. This means you can handle the mapping in the View Model itself. This keeps your controller nice and tidy without having to set up a mapping service.

user659640
  • 29
  • 2
  • Interesting. Seems like my kind of style. **Question:** what do you initially have in your ViewModel constructor that you need to overload it? Currently my ViewModels look almost like DTOs decorated with validation attributes. Just curious. – Ryan Bosinger Aug 08 '12 at 22:58
  • 1
    This works OK in simple scenarios. But what do you do when your ViewModel needs more than a simple Model entity (e.g. of the same name)? Do you just keep putting more and more logic in the constructor and passing more objects in? When this happens I prefer to create a new layer (adaptor) that creates the ViewModel from a set of dependencies it needs. Having this extra layer also lowers coupling (ViewModel is now not coupled to the Model at all). – bytedev Oct 19 '12 at 12:56