Search code examples
c#automapperabp-framework

Ignore destination member in AutoMapper not working


I have the following simple classes and mappings that ignore Id field.
What I noticed is that the .Ignore() does not work when I'm mapping from Eto/Dto to Entity and I do not know the reason behind it.

I'm using the latest ABP 4.4.

public class Country : Entity<string>
{
    public Country() {}
    public Country(string id) { Id = id; }
}

public class CountryDto : EntityDto<string> { }

CreateMap<Country, CountryDto>().Ignore(x => x.Id); // id ignored
CreateMap<CountryDto, Country>().Ignore(x => x.Id); // id not ignored

Mapping code in my test:

var country1 = new Country("XX");
var dto1 = ObjectMapper.Map<Country, CountryDto>(country1);
        
var dto2 = new CountryDto() { Id = "XX" };
var country2 = ObjectMapper.Map<CountryDto, Country>(dto2);

I've also tried the normal AutoMapper long form to ignore instead of ABP's Ignore extension.


Solution

  • AutoMapper maps to destination constructors based on source members.

    There are several ways to ignore id in destination constructors:

    1. Map id constructor parameter to null.
       CreateMap<Country, CountryDto>().Ignore(x => x.Id);
    // CreateMap<CountryDto, Country>().Ignore(x => x.Id);
       CreateMap<CountryDto, Country>().Ignore(x => x.Id).ForCtorParam("id", opt => opt.MapFrom(src => (string)null));
    
    1. Specify ConstructUsing.
       CreateMap<Country, CountryDto>().Ignore(x => x.Id);
    // CreateMap<CountryDto, Country>().Ignore(x => x.Id);
       CreateMap<CountryDto, Country>().Ignore(x => x.Id).ConstructUsing(src => new Country());
    
    1. Rename id param in Country constructor.
    // public Country(string id) { Id = id; }
       public Country(string countryId) { Id = countryId; }
    
    1. DisableConstructorMapping for all maps.
    DisableConstructorMapping(); // Add this
    CreateMap<Country, CountryDto>().Ignore(x => x.Id);
    CreateMap<CountryDto, Country>().Ignore(x => x.Id);
    
    1. Exclude constructors with any parameter named id.
    ShouldUseConstructor = ci => !ci.GetParameters().Any(p => p.Name == "id"); // Add this
    CreateMap<Country, CountryDto>().Ignore(x => x.Id);
    CreateMap<CountryDto, Country>().Ignore(x => x.Id);
    

    Reference: https://docs.automapper.org/en/v10.1.1/Construction.html