1
votes

I have multiple classes that I need to map into 1 class:

This is the source that I'm mapping from(view model):

public class UserBM
{
    public int UserId { get; set; }

    public string Address { get; set; }
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    public string State { get; set; }

    public int CountryId { get; set; }
    public string Country { get; set; }
}

This is how the destination class is(domain model):

public abstract class User
{
    public int UserId { get; set; }

    public virtual Location Location { get; set; }
    public virtual int? LocationId { get; set; }
}

public class Location
{
    public int LocationId { get; set; }

    public string Address { get; set; }
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    public string State { get; set; }

    public virtual int CountryId { get; set; }
    public virtual Country Country { get; set; }

}

This is how my automapper create map currently looks:

Mapper.CreateMap<UserBM, User>();

Based on the documents on automapper codeplex site, this should be automatic but it doesn't work. Address, Address2, etc is still null. What should my createmap look like?

4

4 Answers

1
votes

The reason is because AutoMapper can't map all those flat fields to a Location object by convention.

You'll need a custom resolver.

Mapper.CreateMap<UserBM, User>()
   .ForMember(dest => dest.Location, opt => opt.ResolveUsing<LocationResolver>());

public class LocationResolver : ValueResolver<UserBM,Location>
{
   protected override Location ResolveCore(UserBMsource)
   {
       // construct your object here.
   }
}

However, i dont like this. IMO, a better way would be to encapsulate those properties in your ViewModel into a nested viewmodel:

public class UserBM
{
    public int UserId { get; set; }
    public LocationViewModel Location { get; set; }
}

Then all you have to do is define an additional map:

Mapper.CreateMap<User, UserBM>();
Mapper.CreateMap<LocationViewModel,Location>();

Then it will all work.

You should try and make use of AutoMapper conventions, where possible. And it's certainly possible to make your ViewModel more hierachical, to match the destinations hierachy.

0
votes

EDIT strange this question has been asked by you.. seems to be a same question - i guess i am missing something...

Check this SQ Question

*

Define two mappings, both mapping from the same source to different destinations

*

0
votes

I think you need to make the property names similar to LocationAddress and LocationAddress2 on UserBM for their automatic projection to work, but I may be wrong.

Check out their page on Flattening they have property names that have both property names of the source concatenated like I indicated.

0
votes

Simply follow the naming convention in your target class and prefix the address properties with Location since that's the property name in the source class:

public class UserBM
{
    public int UserId { get; set; }

    public string LocationAddress { get; set; }
    public string LocationAddress2 { get; set; }
    public string LocationAddress3 { get; set; }
    public string LocationState { get; set; }

    public int CountryId { get; set; }
    public string Country { get; set; }
}