Automapper In .NET Core

Introduction 

 
In this article, I will try to explain how to use AutoMapper in our .NET Core applications.
 
I will cover this topic in the following steps:
  1. Introduction
  2. Installation
  3. Registration
  4. Model Creation & Mapping
  5. Reverse Mapping
  6. Complex Object Mapping
  7. Summary
AutoMapper is simple a dependency injection that is used to map one object type to another object type.
 
As you know, before Automapper, when we would map the view model object to the domain model object, then we would manually do for each property. This is not only time consuming, but also error-prone. However, Automapper solves this problem of mapping the source object of the destination object or from the destination object to thesource object.
 

Installation

 
There are two ways to install Automapper in our application
 
Using NuGet Package Manager
 
This is the package that needs to be installed:
 
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
 
Using the Visual studio search option.
 
I am using option two, the Visual studio search option.
 
Please see the attached image:
 
 
After installing this package, you will be able to see this library in your solution package:
 
 

Registration

 
When this NuGet package is installed in your application, the next step is to register the service in ConfigureServices under the startup.cs class.
 
Note
This namespace is required in your startup.cs file:
 
using AutoMapper;
 
Just like this:
  1. // This method gets called by the runtime. Use this method to add services to the container.    
  2. public void ConfigureServices(IServiceCollection services) {  
  3.     services.AddAutoMapper(typeof(Startup));  
  4.     services.AddControllers();  
  5. }  
Now we have completed the installation and registration.
 
The next step is to see how to create a model and its mapping using Automapper.
 

Model Creation & Mapping

 
Suppose we have domain model and its ViewModel, as shown below:
  1. public class Employee {  
  2.     public int Id {  
  3.         get;  
  4.         set;  
  5.     }  
  6.     public string FirstName {  
  7.         get;  
  8.         set;  
  9.     }  
  10.     public string LastName {  
  11.         get;  
  12.         set;  
  13.     }  
  14.     public string Email {  
  15.         get;  
  16.         set;  
  17.     }  
  18.     public string Address {  
  19.         get;  
  20.         set;  
  21.     }  
  22. }  
Let say the view model is like this, which we can use on UI:
  1. public class EmployeeViewModel  
  2. {  
  3.    public string FirstName { getset; }  
  4.    public string LastName { getset; }  
  5.    public string Email { getset; }  
  6. }  
We have created both the domain model and viewmodel.
 
The next step is to create a custom file and inherit it with Profile class provided by AutoMapper.
  1. /// <summary>  
  2. /// AutoMapperProfile: Use to map domain object ot View model and reverse map  
  3. /// </summary>  
  4. public class AutoMapperProfile : Profile  
  5. {  
  6.    public AutoMapperProfile()  
  7.    {  
  8.       CreateMap<Employee, EmployeeViewModel>();  
  9.    }  
  10. }  
Now create your controller and map it using Automapper here:
  1. [Route("api/[controller]")]  
  2. [ApiController]  
  3. public class AutoMapperTestController: ControllerBase {  
  4.     private readonly IMapper _mapper;  
  5.     public AutoMapperTestController(IMapper mapper) {  
  6.         _mapper = mapper;  
  7.     }  
  8.     // GET: api/AutoMapperTest    
  9.     [HttpGet]  
  10.     public IEnumerable < EmployeeViewModel > Get() {  
  11.         var empList = new List < Employee > () {  
  12.             new Employee {  
  13.                 Id = 1, FirstName = "F1", LastName = "L1", Email = "[email protected]"  
  14.             },  
  15.             new Employee {  
  16.                 Id = 2, FirstName = "F2", LastName = "L2", Email = "[email protected]"  
  17.             },  
  18.             new Employee {  
  19.                 Id = 1, FirstName = "F3", LastName = "L3", Email = "[email protected]"  
  20.             }  
  21.         };  
  22.         var employeeViewModel = _mapper.Map < List < EmployeeViewModel >> (empList);  
  23.         return employeeViewModel;  
  24.     }  
  25. }  
Now the obvious question comes to mind, which is what happens when the View model property is different from the domain model.
 
The answer is yes, it is possible that both the object property names are different.
 
In this case, we need to map in the mapping profile using this.
 
Let's take the same example, but ViewModel property is different:
  1. public class EmployeeViewModel {  
  2.     public string FName {  
  3.         get;  
  4.         set;  
  5.     }  
  6.     public string LName {  
  7.         get;  
  8.         set;  
  9.     }  
  10.     public string Email {  
  11.         get;  
  12.         set;  
  13.     }  
  14. }  
Here in this view model, I have changed only the firstName and the Last name. These properties need to be mapped explicitly and there's no need to map for email.
  1. public AutoMapperProfile() {  
  2.     CreateMap < Employee, EmployeeViewModel > ().ForMember(dest => dest.FName, opt => opt.MapFrom(src => src.FirstName)).ForMember(dest => dest.LName, opt => opt.MapFrom(src => src.LastName));  
  3. }  
Once we change this, then let's run our application again. We will see the result below, as expected.
  1. [{"fName":"F1","lName":"L1","email":"[email protected]"},  
  2. {"fName":"F2","lName":"L2","email":"[email protected]"},  
  3. {"fName":"F3","lName":"L3","email":"[email protected]"}]  

Reverse Mapping

 
We seen have mapping from the domain model to the view model, but what about mapping from the view model to the domain model?
 
Actually Automapper  provide the inbuilt method ReverseMap
  1. // Summary:  
  2. // Create a type mapping from the destination to the source type, with validation  
  3. // disabled. This allows for two-way mapping.  
  4. //  
  5. // Returns:  
  6. // Itself  
  7. IMappingExpression<TDestination, TSource> ReverseMap();  
This method will use for reverse mapping in your mapping profile class:
  1. public AutoMapperProfile()  
  2. {  
  3.    CreateMap<Employee, EmployeeViewModel>()  
  4.    .ForMember(dest => dest.FName, opt => opt.MapFrom(src => src.FirstName))  
  5.    .ForMember(dest => dest.LName, opt => opt.MapFrom(src => src.LastName))  
  6.    .ReverseMap();  
  7. }  
In code, when you need to map it, use the method shown below:
  1. var mappedUser = _mapper.Map<Employee>(employeeViewModel);  

Complex Object Mapping

 
We have seen that we are using a simple object, but in a real scenario, we will be using an object inside an object.
 
In the employee model, we may have its address. The address is a separate class.
  1. public class AddressViewModel  
  2. {  
  3.    public string AddressLine1 { getset; }  
  4.    public string City { getset; }  
  5.    public string State { getset; }  
  6.    public string Country { getset; }  
  7. }  
Address Model class:
  1. public class Address  
  2. {    
  3.    public string AddressLine1 { getset; }    
  4.    public string City { getset; }    
  5.    public string State { getset; }    
  6.    public string Country { getset; }    
  7. }    
And our Employee Class is like this:
  1. public class Employee {  
  2.     public int Id {  
  3.         get;  
  4.         set;  
  5.     }  
  6.     public string FirstName {  
  7.         get;  
  8.         set;  
  9.     }  
  10.     public string LastName {  
  11.         get;  
  12.         set;  
  13.     }  
  14.     public string Email {  
  15.         get;  
  16.         set;  
  17.     }  
  18.     public Address Address {  
  19.         get;  
  20.         set;  
  21.     }  
  22. }  
The Employee View Model class is like this:
  1. public class EmployeeViewModel {  
  2.     public int Id {  
  3.         get;  
  4.         set;  
  5.     }  
  6.     public string FirstName {  
  7.         get;  
  8.         set;  
  9.     }  
  10.     public string LastName {  
  11.         get;  
  12.         set;  
  13.     }  
  14.     public string Email {  
  15.         get;  
  16.         set;  
  17.     }  
  18.     public AddressViewModel Address {  
  19.         get;  
  20.         set;  
  21.     }  
  22. }  
Now our profile class will be like this:
  1. public AutoMapperProfile() {  
  2.     //CreateMap<Employee, EmployeeViewModel>();    
  3.     CreateMap < Employee, EmployeeViewModel > ().ForMember(dest => dest.FName, opt => opt.MapFrom(src => src.FirstName)).ForMember(dest => dest.LName, opt => opt.MapFrom(src => src.LastName)).ReverseMap();  
  4.     CreateMap < AddressViewModel, Address > ().ReverseMap();  
  5. }  
  6. }  
Now we have dome the part of complex mapping as well.
 
Let's run the application and see the behavior:
  1. [{  
  2.     "fName""F1",  
  3.     "lName""L1",  
  4.     "email""[email protected]",  
  5.     "address": {  
  6.         "addressLine1""add1",  
  7.         "city""LKO",  
  8.         "state""UP",  
  9.         "country""India"  
  10.     }  
  11. }, {  
  12.     "fName""F2",  
  13.     "lName""L2",  
  14.     "email""[email protected]",  
  15.     "address"null  
  16. }, {  
  17.     "fName""F3",  
  18.     "lName""L3",  
  19.     "email""[email protected]",  
  20.     "address": {  
  21.         "addressLine1""add3",  
  22.         "city""Delhi",  
  23.         "state""Delhi",  
  24.         "country""India"  
  25.     }  
  26. }]  
We got the expected result!
 

Summary

 
There so many features available in Automapper that it is impossible to cover them all in the same article.
 
If you wish to learn more about Automapper, please visit AutoMapperDoc.
 
Here in this article, we have learned:
  • What is Automapper?
  • How to install and use.
  • How to do reverse mapping.
  • How to do mapping for a completed object.
If you have any issues, please download the attached code and run it.
 
I hope this will help you to handle this concept in .NET Core.
 
Thank you for taking your valuable time to read the full article!


Similar Articles