0

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.

aaron
  • 39,695
  • 6
  • 46
  • 102
Kes
  • 448
  • 6
  • 20

1 Answers1

3

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

aaron
  • 39,695
  • 6
  • 46
  • 102
  • thanks @aaron! i tried #1 and #2 both works. still don't quite understand as to why ignore works for entity to eto/dto but not the other way round. essentially it is still a source to a dest. will just keep this in mind =) – Kes Sep 14 '21 at 02:14
  • 1
    It works for property mapping, but not constructor mapping. If you added a constructor with `id` parameter in your Eto/Dto, then it wouldn't work too. – aaron Sep 14 '21 at 03:15