Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to convert a DTO to ViewModel?

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.

like image 607
Ryan Bosinger Avatar asked Aug 08 '12 22:08

Ryan Bosinger


People also ask

Is DTO same as ViewModel?

ViewModel in ASP.NET MVC practice is the same as the DTO, however ViewModel in MVVM pattern is different from DTO because ViewModel in MVVM has behaviors but DTO does not have.

Can a ViewModel have methods?

You can have methods in your ViewModel .

What is ViewModel in asp net core?

In ASP.NET MVC, ViewModel is a class that contains the fields which are represented in the strongly-typed view. It is used to pass data from controller to strongly-typed view.


3 Answers

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.

like image 93
eulerfx Avatar answered Dec 13 '22 14:12

eulerfx


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.

like image 41
Andrew Burgess Avatar answered Dec 13 '22 14:12

Andrew Burgess


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);
    }
}
like image 24
Greg Smith Avatar answered Dec 13 '22 13:12

Greg Smith