One of the great aspects of ASP.NET MVC is how lean and clean the architecture is – there is so little background noise compared to WebForms; possibly the best illustration of this is the difference between the MVC Request Pipeline vs. WebForm Page Lifecycle. The number of hoops you are forced to jump through in WebForms, compared to MVC is quite staggering.
One of the advantages to the noise level being low in MVC is that it is much easier to perceive other patterns (or anti-patterns) that appear in your code; this is especially useful if the patterns represent commodity that could be replaced or refactored into a pattern or framework that requires less manual work to implement or maintain.
The first example of this pattern of commodity code to appear was within our Controllers; repetitive, hand-cranked object conversion code; the web application was based on the S#arp Architecture Framework, which we had extended to support the Spark View Engine and ViewModels and we manually mapped the Domain Entities into the ViewModels before passing to the ViewEngine for rendering. We took an action from our Sprint 2 code review – to see if there was a better way to handle this object conversion. After a little bit of research, I stumbled across Jimmy Bogard’s AutoMapper:
AutoMapper uses a fluent configuration API to define an object-object mapping strategy. AutoMapper uses a convention-based matching algorithm to match up source to destination values. Currently, AutoMapper is geared towards model projection scenarios to flatten complex object models to DTOs and other simple objects, whose design is better suited for serialization, communication, messaging, or simply an anti-corruption layer between the domain and application layer.
AutoMapper is a powerful little framework, with a whole slew of features:
Once we performed the refactoring it became very apparent how well AutoMapper fits into MVC style architecture as it enables easy separation of concerns with regards to object conversion, it was amazing how much cleaner our code became - so much so that we modified the overall solution architecture to incorporate explicit mapping layers for both our ViewModels and to convert external 3rd Party types into our Domain Entities.:
The general pattern of usage of AutoMapper within MVC is as follows:
- Map Controller input into Domain Entities
- Pass Domain Entities into Task Layer to "do stuff"
- Map output of Task Layer (Domain Entities) into ViewModel
- Pass ViewModel to ViewEngine (Spark)
Simple, slick and clean.
To formalise the Mapping Layer and make it testable we implemented a simple interface:
public interface IMapper<TInput, TOutput>
TOutput MapFrom(TInput input);
Next we implement a custom marker interface so that we could resolve the Mapper from the DI container and we adopted the naming convention:
<Input Type><Output Type>Mapper
public interface IEditModelEntityMapper : IMapper<EditModel, Entity>
Then implement the interface, configuring the AutoMapper convertions in the constructor:
public class EditModelEntityMapper : IEditModelEntityMapper
.ForMember(x => x.Property, y => y.MapFrom(z => z.Property));
public Entity MapFrom(EditModel input)
return Mapper.Map<EditModel, Entity>(input);
Next, we use the Mapper inside a ASP.NET MVC Controller (injecting the dependencies into the constructor):
public class CustomController : Controller
private readonly IEditModelEntityMapper editModelEntityMapper;
private readonly IOutputViewModelMapper outputViewModelMapper;
private readonly ITasks tasks;
public CustomController(ITasks tasks,
this.tasks = tasks;
this.editModelEntityMapper = editModelEntityMapper;
this.outputViewModelMapper = outputViewModelMapper;
public ActionResult Index(EditEntity input)
var entity = this.editModelEntityMapper.MapFrom(input);
var output = this.tasks.DoSomething(entity);
var viewModel = this.outputViewModelMapper.MapFrom(output);
We were a little sceptical at the start of the project that AutoMapper would "cut the mustard" when it came to the performance requirements of a public facing, high load, e-commerce site because of the amount of reflection AutoMapper uses at its core, but after some cursory testing we were incredibly impressed with the performance of the solution under load.
The result of switching to AutoMapper was a huge reduction in commodity plumbing code, it also meant we had a formalised pattern for separating the concern of performing object conversion that was simple, elegant and most importantly - testable. Another side-effect of using AutoMapper was that it resulted in our Controllers becoming spartan, lean and testable. By following a strict naming convention it promoted code discovery and reuse: if a developer was looking to convert EntityA into ViewModelB it’s very simple to use ReSharper to look for the EntityAViewModelBMapper type.
Work smarter, not harder.