How to use View Models

I’ve had quite a few discussions around view models and the different patterns around using them in MVC.  A while back I read an interesting article by Steve Michelotti about the subject and I would like to expand on his arguments.

He argues that there are 3 different models for constructing view models – I would like to argue that there are 3 different ways we can use view models in our applications.

Using your domain model for displaying and posting data

The first way of using view models is to use your domain model as your view model.  You will pass your domain model to your views directly for displaying data and the view will post domain objects to the controller directly.

public ActionResult Index()
{
    return View("Index", service.GetContacts());
}

public ActionResult Add(Contact contact)
{
    service.Add(contact);

    return RedirectToAction("Index");
}

This approach is very easy to implement and straightforward.  There is no mapping between view models and domain models and code is clean and concise.

Unfortunately there are a couple of drawbacks with using this approach.  The first is that there is often a mismatch between what the domain model contains and what we want to display.  The domain model often contains more data than the view actually requires – not a massive issue, but worth noting.  The second issue is that we often deal with multiple domain objects and once in our views.  This becomes particularly annoying when trying to post data that belongs to more than one domain object – the controllers tend to do too much and the code becomes cluttered and difficult to test or maintain.

Using the view model for displaying and posting data

The second approach is to always use view models inside our views.  When displaying data we will perform the mapping from the domain model to the view model and when posting data we will map from the view model back to the domain model.

public ActionResult Index()
{
    var widgets = service.GetWidgets();

    var list = new List<WidgetViewModel>();
    foreach (var widget in widgets)
    {
        list.Add(new WidgetViewModel { Color = widget.Color, Size = widget.Size, Texture = widget.Texture });
    }

    return View("Index", list);
}

public ActionResult Add(WidgetViewModel viewModel)
{
    var widget = new Widget();

    widget.Color = viewModel.Color;
    widget.Size = viewModel.Size;
    widget.Texture = viewModel.Texture;

    service.Add(widget);

    return RedirectToAction("Index");
}

This approach has more overhead than the first option, but is much more flexible.  In this example the mapping code is very tedious, but I find more often than not I require the flexibility available with the view model, especially when adding or updating.

The obvious drawback here is the added mapping code and the need to create a separate view model object – less code is better.

Using the domain model for displaying and view model for posting data

The third approach (which is the one I prefer) is a hybrid approach – use the domain model for displaying data and the view model for adding or updating.  The means that we will always pass domain objects to the views and the views will always pass view model objects to the controllers.

public ActionResult Index()
{
    return View("Index", service.GetUsers());
}

public ActionResult Add(UserViewModel viewModel)
{
    var user = new User();

    user.Name = viewModel.Name;
    user.Surname = viewModel.Surname;
    user.IdNumber = viewModel.IdNumber;

    service.Add(user);

    return RedirectToAction("Index");
}

I feel this approach has the least amount of overhead in terms of mapping between the domain model and view model while maintaining all the necessary flexibility.  I find that simply using a subset of the domain model when displaying data is pretty straightforward and most of my issues arise when trying to post data back to the server – hence the use of the view model.

Summary

I think it’s very important to choose the approach that works for you and consistently use it throughout your application.  Keep in mind that each approach has advantages and disadvantages and choose one that works for you.

Also keep in mind that AutoMapper can alleviate much of the pain around the mapping between domain and view models.  I haven’t written an MVC application using view models for displaying and posting data with AutoMapper performing all the mapping, but it definitely seems like a very cool approach.

Happy coding.