Starfish
Starfish

Reputation: 3584

Automapper: How to convert a list of ids to a list of objects

I want to convert an array of ids from a dto to a list of related objects using AutoMapper, however, the mapping only works one way.

The current setup is the following:

public class Group
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Location> Locations { get; set; }
}

public class GroupDto
{
    public int id { get; set; }
    public string name { get; set; }
    public int[] locationIds { get; set; }
}

And the code in the GroupProfile:

CreateMap<Group, GroupDto>()
    .ForMember(dest => dest.id, opt => opt.MapFrom(src => src.Id))
    .ForMember(dest => dest.name, opt => opt.MapFrom(src => src.Name))
    .ForMember(dest => dest.locationIds, opt => 
        opt.MapFrom(src => src.Locations.Select(l => l.Id).ToArray()));

This code works when I try to convert a Group to a GroupDto, but not when I try it the other way around. The following error occurs:

An unhandled exception has occurred while executing the request. AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types: GroupDto -> Group

Also, when I do it without the AutoMapper like below, it just works:

Group group = new Group
{
    Name = groupDto.name,
    Locations = _context.Locations
        .Where(l => groupDto.locationIds.Contains(l.Id))
        .ToList()
};

Help is appreciated!

Upvotes: 0

Views: 1729

Answers (2)

Yong Shun
Yong Shun

Reputation: 51440

Your AutoMapper doesn't find the mapping from GroupDto to Group.

  1. You need .ReverseMap() to support reverse mapping from Group to GroupDto.

  2. Mapping configuration for mapping from Location to int and vice versa via .ConstructUsing().

  3. Modify the mapping for the member locationIds.

  4. The mapping for the members id and name may be omitted as AutoMapper will perform the mapping between members by ignoring case-sensitive.

CreateMap<Location, int>()
    .ConstructUsing(src => src.Id);
            
CreateMap<int, Location>()
    .ConstructUsing(src => new Location { Id = src });
            
CreateMap<Group, GroupDto>()
    .ForMember(dest => dest.locationIds, opt => opt.MapFrom(src => src.Locations))
    .ReverseMap();

Demo @ .NET Fiddle

Upvotes: 1

klekmek
klekmek

Reputation: 573

AutoMapper cannot convert an int[] to a ICollection<Location>. You need to create a seperate mapping for this.

CreateMap<GroupDto, Group>()
    .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.id))
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.name))
    .ForMember(dest => dest.Locations, opt => opt.MapFrom(src => src.Select(l => new Location { Id = src }));

I haven't tested this snippet so I hope you get the gist of it.

Upvotes: 1

Related Questions