.NET Technical Guide: AutoMapper

This Technology Guide was created to help people that are just beginning to learn AutoMapper. This is the first in a series of Technology Guides covering useful technologies. If you find it useful or have any feedback, please reply in the comments!

What Is AutoMapper?

With the advent of layered architectures like N-Tier Architecture and Onion Architecture, it is very common to have duplicate objects in multiple layers. AutoMapper is a tool that allows you to map from one object to another automatically, without having to repeatedly write boilerplate-mapping code.

When should I use AutoMapper?

Let’s say we have two objects, A and B, and we want to create an instance of object B from the data in object A. It’s pretty simple to create a common function that takes in an A and uses the data to set B. This seems to be a simple solution to the problem of mapping between layers, so why would anyone choose to use AutoMapper?

AutoMapper is useful because it can intelligently map objects based on their attribute names and types. By using convention over configuration, it automatically maps properties with the same names, preventing us from writing that boilerplate code at all.

For example, lets say that we have two objects, Name and FullName:

public class Name {      string FirstName { get; set; }      string LastName { get; set; } }

public class FullName {      string FirstName { get; set; }      string LastName { get; set; }      string MiddleName { get; set;} }

As you can see from the pseudo-code above, both Name and FullName have the attributes FirstName and LastName. If we were to use AutoMapper to create a map from name to FullName, when the mapping occurred, AutoMapper would know to map the two attributes in Name to their equivalents in FullName without us having to explicitly configure it to do so. This can save us a lot of time when mapping similar large objects, and is the main reason to use AutoMapper.

Setting up AutoMapper

Adding AutoMapper to a project is fairly simple. First, go to the Nuget Package Manager and download AutoMapper into your project. Next, find the App Start folder in your project and add a new file called AutoMapperConfig.cs inside that folder. The file should be set up as follows:

public static class AutoMapperConfig { public static void RegisterMappings() { // Mapping setup goes here } }

Next, find your Global.asax file. Inside it, find the Application_Start() method and add a call AutoMapperConfig.RegisterMappings() to the method. These steps will cause your RegisterMappings() function to run at the time of application startup. Once this is done you are ready to start adding Mappings to the AutoMapperConfig file and using the mapping in your project.

Note: In larger projects when Automapper is used repeatedly or solutions that contain multiple projects, it might be necessary to have multiple MappingConfig files. In these cases it is no longer appropriate to name the file generically like we did above (AutoMapperConfig). Instead, you should name the class so that others should be able to guess what’s being mapped just by looking at the name.

Using Automapper: Creating a Map

Let’s say we have a situation where we have an object, Individual, that we use in our back end code. The situation arises where we need to use Individual in our front end code, and we decide that we want to push a flat version of Individual called IndividualViewModel up from the back end to the front end. However, Individual has an object Name in it that has attributes itself. The objects are structured as follows:

public class Individual { DateTime Birthday { get; set; } Name IndividualName{ get; set; } }   public class Name { string First { get; set; } string Last { get; set; } }   public class IndividualViewModel { DateTime Birthday { get; set; } string FirstName { get; set; } string LastName { get; set; } }

In order to create a map from Individual to IndividualViewModel, we would need to add the following code to the RegisterMappings() function in AutoMapperConfig.cs:

AutoMapper.Mapper.CreateMap();

This would create a map that properly maps Birthday, because it is named the same in both objects. However, since FirstName and Lastname are both within Name in Individual, they would not properly map. So in order to map them properly, we need to add on to our map creator:

AutoMapper.CreateMap() .ForMember(dest => dest.FirstName, mapper => mapper.MapFrom(src => src.Name.First) .ForMember(dest => dest.LastName, mapper => mapper.MapFrom(src => src.Name.Last);

The ForMember() function allows you to set mappings that would not  be automatically set. It takes two inputs. In the first input, you tell FromMember which attribute on your destination object you want to map to. In the second input, you tell FromMember which attribute on the source object you want AutoMapper to map from.

Note: AutoMapper will map nested attributes to an attribute on a flat object if the naming is the same. So, in the example above if the destination attribute for the first name was dest.First, Automapper would have handled it properly and it would have been unnecessary to register it explicitly by calling ForMember().

 Using Automapper: Invoking Mappings

Calling a mapping is very simple once it has been set up and registered. Using our example above, all we would need to do is call the following code if we had an Individual:

var individualViewModel = AutoMapper.Mapper.Map(individual);

 AutoMapper in Tests

Since AutoMapper is set up in the application start, it will not be set up in test runs (because the application start is not run). For example, when running unit tests, any code that relies in AutoMapper will throw an exception because no mappings have been registered.

To fix this, you just need to tear down and then set up your mappings in the Setup section of your test fixture. We tear down the mapping to begin the setup to make sure that no mappings are carried over from another unit test being run at the same time.

To tear down the Mapper, simply call Mapper.Reset(). To setup the mapper, reference your AutoMapperConfig and call RegisterMappings(). So your Setup function should look as follows:

[SetUp] public void Setup() { Mapper.Reset(); AutoMapperConfig.RegisterMappings(); }

Note: In cases where you have separated out your AutoMapperConfig into multiple mapping files, you only need to set up the mapping config files that you are using.

FAQ

  • How do I perform nested mapping (how do I map an object, and also map the objects that it contains?

In order to perform a nested mapping you must call set up both mappings, and in the mapping setup of the container object, call the mapping that you set up for the nested object.

Lets say you have Father object and a Child object, and Father contains a child. You also have a FatherViewModel and a ChildViewModel. Your goal is to map from a Father to a FatherViewModel, and you want the contained child to be mapped to a ChildViewModel. The mappings would be set up as follows:

AutoMapper.Mapper.CreateMap< Child, ChildViewModel>(); AutoMapper.Mapper.CreateMap < Father, FatherViewModel>() .ForMember(dest => dest.Child, mapper => mapper.MapFrom(child => Mapper.Map(child)));

  • Is it possible to use naming conventions to have AutoMapper map nested objects for me?

Yes, it is possible. If your viewModel’s name for a field is the concatenation of the path to get to that field in the object, then AutoMapper will map it correctly. For example assume we have a Worker object, which has a Job object, which contains a string Code:

public Worker { public Job Job { get; set; } } public Job { public String Code { get; set; } }

If we set our WorkerViewModel up to have the attribute JobCode – the concatenation of the names of the class (Job) and the property (Code) – then AutoMapper will map it for us without having to specifically call it out.

public WorkerViewModel { public string JobCode { get; set; } }

Resources

alex-hoffman

As a consultant with Excella Consulting, Alex Hoffman specializes in C# and JavaScript. Using Scrum and Agile Engineering practices, he has delivered impactful and reliable solutions to several proje