Juan Salvador Portugal
Juan Salvador Portugal

Reputation: 1339

Map property to property of a collection automapper

I have two entities

public class A{
    public string Example { get; set; }
    public ICollection<B> BCollection { get;set; } = new HashSet<B>();
}

public class B {
    public string MyProperty { get; set; }
}

And a simple ViewModel

public class AFirstLoadViewModel {
    public string Example { get; set; }
    public string MyProperty { get; set; }
}

The thing, is, this viewmodel will be use only in the first data entry, when A will only have one B object inside.

So, i'm trying to map a object like this:

var source = new AFirstLoadViewModel
{
    Example = "example",
    MyProperty = "myproperty"
}

to this

var destination = new A {
    Example = "example"
    BCollection = new List<B> {
        new B { MyProperty = "myproperty" }
    }
}

I try to do the trick using ForPath and BeforeMap without luck

CreateMap<AFirstLoadViewModel, A>()
    .ForMember(x => x.Example, c => c.MapFrom(x => x.Example))
    .ForPath(x => x.BCollection.First().MyProperty, c => c.MapFrom(x => x.MyProperty))
    .BeforeMap((viewModel, entity) => {
        if(!entity.BCollection.Any())
            BCollection.Add(new B());
    });

But i get

System.ArgumentOutOfRangeException: Only member accesses are allowed.

How can i deal with it?

I clarify: both, view model and model have many more properties, the question classes are by way of example

Edit:


I try the solution proposed by Johnatan, and it works, the problem here, is that i cant Unit Testing anymore.

I'm testing with

var config = new MapperConfiguration(cfg => cfg.CreateMap<AFirstLoadViewModel, A>(MemberList.Source));

And when i call config.AssertConfigurationIsValid() fails because the MyProperty property is not mapped

Upvotes: 3

Views: 3691

Answers (2)

Lee
Lee

Reputation: 594

The problem is you are trying to map to .First(). First does not yet exist because the query is on a null / empty collection. You can't assign to the .First() element in a collection if one does not exist already. Instead just map as a collection directly.

CreateMap<AFirstLoadViewModel, A>()
.ForMember(x => x.Example, c => c.MapFrom(x => x.Example))
.ForMember(x => x.BCollection, c => c.MapFrom(x => new [] { new B { MyProperty = x.MyProperty } }));

Upvotes: 2

Johnathan Barclay
Johnathan Barclay

Reputation: 20372

CreateMap<AFirstLoadViewModel, A>()
    .ForMember(x => x.Example, c => c.MapFrom(x => x.Example))
    .ForMember(x => x.BCollection, c => c.MapFrom(x => new [] { new B { MyProperty = x.MyProperty } })); 

Upvotes: 1

Related Questions