Author : HASSAN MD TAREQ | Updated : 2020/08/01

What is AutoMapper?

  • AutoMapper is an object-to-object mapper. Object-object mapping works by transforming an input object of one type into an output object of a different type
  • See: AutoMapper Usage Guidelines
  • Automapper Github repo: https://github.com/AutoMapper/AutoMapper
  • Automapper API Doc: https://docs.automapper.org/en/stable/index.html
  • How do I test my mappings?

Installation

Install-Package AutoMapper

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

Setup

  • you only need one MapperConfiguration instance typically per AppDomain and should be instantiated during startup.
  • a good way to organize your mapping configurations is with profiles. Create classes that inherit from Profile and put the configuration in the constructor
  • if you have only one layer where you need to map between your models, I would recommend not to use AutoMapper Profiles and just go with a simple solution
  • profiles allow you to group common configuration and organize mappings by usage. This lets you put mapping configuration closer to where it’s used, instead of a single file of configuration that becomes impossible to edit/maintain

Simple setup

var config = new MapperConfiguration(cfg => {

    cfg.CreateMap<FooEntity, FooDto>();
    
    // or
    
   cfg.CreateMap<FooEntity, FooDto>()
       .ForMember(dest => dest.FullName, opts => opts.MapFrom(src => $"{src.FirstName} {src.LastName}"));
    
    // ... ... ...
});

var mapper = config.CreateMapper(); // or IMapper mapper = new Mapper(config);

var fooDto = mapper.Map<FooDto>(fooEntity); // type is inferred: var dest = mapper.Map<FooEntity, FooDto>(...)
Simple setup with profile

FooProfile.cs

public class FooProfile : Profile
{
  public FooProfile()
  {
  
   CreateMap<FooEntity, FooDto>()
       .ForMember(dest => dest.FullName, opts => opts.MapFrom(src => $"{src.FirstName} {src.LastName}"));
       
    // ... ... ...
  }
}

Using FooProfile

var config = new MapperConfiguration(cfg => {
    cfg.AddProfile<FooProfile>();
});

var mapper = config.CreateMapper();

var fooDto = mapper.Map<FooDto>(fooEntity);

AutoMapper in aspnet core with Dependency Injection

  • Dependency: Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
  • AddAutoMapper() will scan the aspnet core app project (not library project) and add all profiles derived form AutoMapper Profile (you just need to create profiles)
  • for library project see: https://lostechies.com/jimmybogard/2016/07/20/integrating-automapper-with-asp-net-core-di/
  • see: https://stackoverflow.com/questions/40114996/automapper-implementation-in-asp-net-core-mvc

AddAutoMapper() in Startup.cs

services.AddAutoMapper(typeof(Startup));

// ... ... ...

If models are in different package

services.AddAutoMapper(typeof(a_profile_classe_in_other_assembly).GetTypeInfo().Assembly);

See: https://github.com/AutoMapper/AutoMapper/issues/2300#issuecomment-342157947

Get IMapper by DI

FooService.cs

public class FooService {

  private readonly IMapper _mapper;
  
  private readonly IFooRepo _repo;
  
  public UserController(IMapper mapper, IFooRepo repo) {
    _mapper = mapper;
    _repo = repo;
  }

  public FooDto GetFoo(long id){
  
    FooEntity fooEntity = _repo.GetFoo(id);
    
    FooDto fooDto = _mapper.Map<FooDto>();
    
    return fooDto 
  }
  
  // ... ... ...
}

Mappings

Ignore property

// UpdateEmployeeDto => Employee
CreateMap<UpdateEmployeeDto, Employee>().ForMember(dest => dest.Id, opts => opts.Ignore());

Ignore null values

// Just for compying values
CreateMap<Employee, Employee>().ForMember(dest => dest.Id, opts => opts.Ignore())
    .ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));

See:

  • https://stackoverflow.com/questions/43947475/how-to-ignore-null-values-for-all-source-members-during-mapping-in-automapper-6
  • To set default value for null: http://docs.automapper.org/en/stable/Null-substitution.html#null-substitution