8

Basically I have this class which represents 1:1 with my database

public class User
{
    public int UserID { get; set; }
    public string Username { get; set; }
    public string Role { get; set; }
}

and I have this viewmodel

public class UserEditViewModel
{
    public UserEditViewModel()
    {
        Roles = new List<string>();
    }

    public int UserID { get; set; }
    [Required]
    public string Username { get; set; }
    [Required]
    public List<string> Roles { get; set; }
}

I have no idea how to map between these 2. My current setup :

Mapper.CreateMap<UserEditViewModel, User>().ReverseMap();

4 Answers 4

12

There is something similar to your questiong here, please can you check this out AutoMapper: Collection to Single string Property

PS: This is an example for mapping collection to single string property probably your example should look like below;

Mapper.CreateMap<User, UserEditViewModel>()
    .ForMember(dest => dest.Roles,
    m => m.MapFrom(src => src.Role.Split(',').ToList()));

And mapping the instances like below;

User myUser = new User();
myUser.Role = "r1,r2,r3,r4,r5";
myUser.UserID = 1;
myUser.Username = "MyUserName";

UserEditViewModel result = Mapper.Map<UserEditViewModel>(myUser);

enter image description here

2020 Edit: Since Expression.Call API does not support optional parameter and you should Replace src.Role.Split(',') with src.Role.Split(',', System.StringSplitOptions.None) or src.Role.Split(',', System.StringSplitOptions.RemoveEmptyEntries)

Sign up to request clarification or add additional context in comments.

4 Comments

Is it still possible to use ReverseMap or do we need to do the opposite the other way?
It would be great if this worked, but I get CS0854 An expression tree may not contain a call or invocation that uses optional arguments on the Split call.
Hey @DavidDombrowsky , since options parameter of Split is optional and Expression.Call api does not support method calls with optional parameter you need to provide it yourself or you may create you own method which wraps Split. This is required because of the AutoMapper's changes.
Thank you @CihanUygun. Wrapping it in a static function that does the same thing without optional params seems to do the trick.
4

To map a string to a collection Cihan Uygun's answer works, only to fix the error

CS0854 An expression tree may not contain a call or invocation that uses optional arguments

which is caused in later updates you should Replace src.Role.Split(',') with src.Role.Split(',', System.StringSplitOptions.None) or src.Role.Split(',', System.StringSplitOptions.RemoveEmptyEntries)

To do the reverse mapping just use src => string.Join(',', src.Roles)

Source for the error fix: https://newbedev.com/mapping-string-to-list-string-and-vice-versa-using-automapper

Comments

1

If you want to concatenate all values in your list of string you need to use string.Join. In mapper you need to use ForMember method.

From UserEditViewModel to User:

Mapper.CreateMap<User, UserEditViewModel>().ForMember(user => user.Role, opt => opt.MapFrom(userEdit => string.Join(", ", userEdit.Roles)));

From User to UserEditViewModel:

Mapper.CreateMap<UserEditViewModel, User>().ForMember(userEdit => userEdit.Roles, opt => opt.MapFrom(user => user.Role.Split(",").ToList()));

Comments

0

I think you should be able to use the AutoMapper AfterMap, something like this:

.AfterMap((src,dest) => dest.Roles.Add(src.Role))

Credit to the answer here: Map a property to a collection item

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.