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 it for each property. This is not only time-consuming but also error-prone. However, Automapper solves this problem of mapping the source object to the destination object or from the destination object to the source 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 sStudiosearch option.

I am using option two, the Visual sStudiosearch option.

Please see the attached image.

Browser

After installing this package, you will be able to see this library in your solution package:

Auto mapper

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

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
    services.AddAutoMapper(typeof(Startup));
    services.AddControllers();
}

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 a domain model and its ViewModel, as shown below.

public class Employee {
    public int Id {
        get;
        set;
    }
    public string FirstName {
        get;
        set;
    }
    public string LastName {
        get;
        set;
    }
    public string Email {
        get;
        set;
    }
    public string Address {
        get;
        set;
    }
}

Let's say the view model is like this, which we can use on UI.

public class EmployeeViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

We have created both the domain model and the model.

The next step is to create a custom file and inherit it with the Profile class provided by AutoMapper.

/// <summary>
/// AutoMapperProfile: Use to map domain object ot View model and reverse map
/// </summary>
public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        CreateMap<Employee, EmployeeViewModel>();
    }
}

Now create your controller and map it using Automapper here.

[Route("api/[controller]")]
[ApiController]
public class AutoMapperTestController : ControllerBase 
{
    private readonly IMapper _mapper;
    public AutoMapperTestController(IMapper mapper) 
    {
        _mapper = mapper;
    }
    // GET: api/AutoMapperTest
    [HttpGet]
    public IEnumerable<EmployeeViewModel> Get() 
    {
        var empList = new List<Employee>() 
        {
            new Employee { Id = 1, FirstName = "F1", LastName = "L1", Email = "[email protected]" },
            new Employee { Id = 2, FirstName = "F2", LastName = "L2", Email = "[email protected]" },
            new Employee { Id = 1, FirstName = "F3", LastName = "L3", Email = "[email protected]" }
        };
        var employeeViewModel = _mapper.Map<List<EmployeeViewModel>>(empList);
        return employeeViewModel;
    }
}

Local host

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, but the object property names may be different.

In this case, we need to map in the mapping profile using this.

Let's take the same example, but the ViewModel property is different.

public class EmployeeViewModel 
{
    public string FName { get; set; }
    public string LName { get; set; }
    public string Email { get; set; }
}

Here in this view model, I have changed only the first name and the Last name. These properties need to be mapped explicitly and there's no need to map for email.

public AutoMapperProfile() 
{
    CreateMap<Employee, EmployeeViewModel>()
        .ForMember(dest => dest.FName, opt => opt.MapFrom(src => src.FirstName))
        .ForMember(dest => dest.LName, opt => opt.MapFrom(src => src.LastName));
}

Once we change this, then let's run our application again. We will see the result below, as expected.

[
    {"fName":"F1","lName":"L1","email":"[email protected]"},
    {"fName":"F2","lName":"L2","email":"[email protected]"},
    {"fName":"F3","lName":"L3","email":"[email protected]"}
]

Reverse Mapping

We have seen mapping from the domain model to the view model, but what about mapping from the view model to the domain model?

Automapper provides the inbuilt method ReverseMap.

// Summary:
// Create a type mapping from the destination to the source type, with validation
// disabled. This allows for two-way mapping.
//
// Returns:
// Itself
IMappingExpression<TDestination, TSource> ReverseMap();

This method will be used for reverse mapping in your mapping profile class.

public AutoMapperProfile()
{
    CreateMap<Employee, EmployeeViewModel>()
        .ForMember(dest => dest.FName, opt => opt.MapFrom(src => src.FirstName))
        .ForMember(dest => dest.LName, opt => opt.MapFrom(src => src.LastName))
        .ReverseMap();
}

In code, when you need to map it, use the method shown below.

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.

public class AddressViewModel
{
    public string AddressLine1 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }
}

Address Model class

public class Address
{
    public string AddressLine1 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }
}

And our Employee Class is like this

public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public Address Address { get; set; }
}

The Employee View Model class is like this.

public class EmployeeViewModel
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public AddressViewModel Address { get; set; }
}

Now our profile class will be like this.

public AutoMapperProfile()
{
    //CreateMap<Employee, EmployeeViewModel>();
    CreateMap<Employee, EmployeeViewModel>()
        .ForMember(dest => dest.FName, opt => opt.MapFrom(src => src.FirstName))
        .ForMember(dest => dest.LName, opt => opt.MapFrom(src => src.LastName))
        .ReverseMap();
    CreateMap<AddressViewModel, Address>().ReverseMap();
}

Now we have done the part of complex mapping as well.

Let's run the application and see the behavior.

[
    {
        "fName": "F1",
        "lName": "L1",
        "email": "[email protected]",
        "address": {
            "addressLine1": "add1",
            "city": "LKO",
            "state": "UP",
            "country": "India"
        }
    },
    {
        "fName": "F2",
        "lName": "L2",
        "email": "[email protected]",
        "address": null
    },
    {
        "fName": "F3",
        "lName": "L3",
        "email": "[email protected]",
        "address": {
            "addressLine1": "add3",
            "city": "Delhi",
            "state": "Delhi",
            "country": "India"
        }
    }
]

We got the expected result!

Summary

There are 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!