Asp.net-mvc – How to map View Model back to Domain Model in a POST action

asp.net-mvcautomapperdomain-driven-designseparation-of-concernsviewmodel

Every article found in the Internet on using ViewModels and utilizing Automapper gives the guidelines of the "Controller -> View" direction mapping. You take a domain model along with all Select Lists into one specialized ViewModel and pass it to the view. That's clear and fine.
The view has a form, and eventually we are in the POST action. Here all the Model Binders come to the scene along with [obviously] another View Model which is [obviously] related to the original ViewModel at least in the part of naming conventions for the sake of binding and validation.

How do you map it to your Domain Model?

Let it be an insert action, we could use the same Automapper. But what if it was an update action? We have to retrieve our Domain Entity from the Repository, update it's properties according to the values in the ViewModel and save to the Repository.

ADDENDUM 1 (9th of February 2010): Sometimes, assigning Model's properties is not enough. There should be taken some action against Domain Model according to the values of View Model. I.e., some methods should be called on Domain Model. Probably, there should be a kind of an Application Service layer which stands between Controller and Domain in order to process View Models…


How to organize this code and where to place it to achieve the following goals?

  • keep controllers thin
  • honor SoC practice
  • follow Domain-Driven Design principles
  • be DRY
  • to be continued …

Best Answer

I use an IBuilder interface and implement it using the ValueInjecter

public interface IBuilder<TEntity, TViewModel>
{
      TEntity BuildEntity(TViewModel viewModel);
      TViewModel BuildViewModel(TEntity entity);
      TViewModel RebuildViewModel(TViewModel viewModel); 
}

... (implementation) RebuildViewModel just calls BuildViewModel(BuilEntity(viewModel))

[HttpPost]
public ActionResult Update(ViewModel model)
{
   if(!ModelState.IsValid)
    {
       return View(builder.RebuildViewModel(model);
    }

   service.SaveOrUpdate(builder.BuildEntity(model));
   return RedirectToAction("Index");
}

btw I don't write ViewModel I write Input cuz it's much shorter, but that just not really important
hope it helps

Update: I'm using this approach now in the ProDinner ASP.net MVC Demo App, it's called IMapper now, there's also a pdf provided where this approach is explained in detail

Related Topic