Automapper: UseDestinationValue does not work for collections?
Let’s assume there are classes:
public class Foo { public List<Bar> Bars { get; set; } } public class Bar { public string Name { get; set; } public string Description { get; set; } } public class FooDto { public List<BarDto> Bars { get; set; } } public class BarDto { public string Name { get; set; } } public class MapperProfile : Profile { public MapperProfile() { CreateMap<FooDto, Foo>(); CreateMap<BarDto, Bar>() .ForMember(dest => dest.Description, opt => opt.UseDestinationValue()); } }
If I’m using one-to-one mapping, everything is working as expected:
var mapper = new Mapper(new MapperConfiguration(e => e.AddProfile(typeof(MapperProfile)))); var bar = new Bar { Name = "name", Description = "description" }; var barDto = new BarDto { Name = "updated name" }; mapper.Map(barDto, bar); Console.WriteLine(bar.Name); Console.WriteLine(bar.Description); // Output: // updated name // description
But this is not working for collections:
var mapper = new Mapper(new MapperConfiguration(e => e.AddProfile(typeof(MapperProfile)))); var foo = new Foo { Bars = new List<Bar> { new Bar { Name = "name", Description = "description", } } }; var fooDto = new FooDto { Bars = new List<BarDto> { new BarDto { Name = "updated name" } } }; mapper.Map(fooDto, foo); foreach (var bar in foo.Bars) { Console.WriteLine(bar.Name); Console.WriteLine(bar.Description); } // Output: // updated name //
Bar’s Description
is null after mapping (have tested on 9.0.0
and 10.0.0
versions).
What is the reason, how to fix?
Finally, I have found the solution. Automapper clears the destination collection before mapping, that is why all properties are set to default. AutoMapper.Collection can helps in this case.
public class Foo { public List<Bar> Bars { get; set; } } public class Bar { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } } public class FooDto { public List<BarDto> Bars { get; set; } } public class BarDto { public int Id { get; set; } public string Name { get; set; } } public class MapperProfile : Profile { public MapperProfile() { CreateMap<FooDto, Foo>(); CreateMap<BarDto, Bar>() .EqualityComparison((src, dest) => src.Id == dest.Id); } }
And using like this:
var mapper = new Mapper(new MapperConfiguration(e => { e.AddCollectionMappers(); e.AddProfile(typeof(MapperProfile)); })); var foo = new Foo { Bars = new List<Bar> { new Bar { Id = 1, Name = "name", Description = "description", } } }; var fooDto = new FooDto { Bars = new List<BarDto> { new BarDto { Id = 1, Name = "updated name" } } }; mapper.Map(fooDto, foo); foreach (var bar in foo.Bars) { Console.WriteLine(bar.Name); Console.WriteLine(bar.Description); } // Output: // updated name // description