0

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?

hcp
  • 3,268
  • 6
  • 26
  • 41

1 Answers1

1

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
hcp
  • 3,268
  • 6
  • 26
  • 41
  • I tried adding this package for my case, but Automapper seems to still be ignoring the configuration I set for my child object. https://stackoverflow.com/questions/70990557/automapper-not-properly-mapping-child-collection – DLeh Feb 07 '22 at 14:51