Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Map a Complex Object to a List of Objects using AutoMapper

5.00/5 (8 votes)
26 Jul 2022CPOL1 min read 65.1K   219  
Conversion of complex object to a list of objects
In this post, we will focus on the conversion of a complex object to a list of objects.

Background

AutoMapper is a simple library that helps us to transform one object type to another. It is a convention based object to object mapper, that requires minimal configuration. Here, we will focus on the conversion of a complex object to a list of objects.

Installation & Configuration

To use AutoMapper in the web application, you need to install packages from NuGet.

Install-Package AutoMapper
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

Add an AutoMapper profile class to the project. This profile class will hold mapping rules.

C#
public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
       /*mapping rules here*/
    }
}

Inside ConfigureServices(IServiceCollection services) of Startup.cs, add:

C#
/*Automapper*/
services.AddAutoMapper(typeof(Startup));

This will load all AutoMapper profiles from the project assembly.

Object to List

Here, we will convert a complex Team model to IEnumerable<TeamMember>. Team has nested List<People> property and other properties. TeamMember is a plain POCO model.

Model

Source Model
C#
public class Team
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<People> Members { get; set; }
}

public class People
{
    public int Id { get; set; }
    public string Name { get; set; }
}
Destination Model
C#
public class TeamMember
{
    public int TeamId { get; set; }
    public string TeamName { get; set; }
    public int PeopleId { get; set; }
    public string PeopleName { get; set; }
}

Map Settings

We need to place these mapping rules inside the AutoMapper profiles constructor.

C#
CreateMap<Team, TeamMember>()
    .ForMember(d => d.TeamId, opt => opt.MapFrom(s => s.Id))
    .ForMember(d => d.TeamName, opt => opt.MapFrom(s => s.Name));
CreateMap<People, TeamMember>()
    .ForMember(d => d.PeopleId, opt => opt.MapFrom(s => s.Id))
    .ForMember(d => d.PeopleName, opt => opt.MapFrom(s => s.Name));
CreateMap<Team, IEnumerable<TeamMember>>()
    .ConvertUsing<TeanToTeamMemberListConverter>();
  • CreateMap<Team, TeamMember>() convets Team to TeamMember
  • CreateMap<People, TeamMember>() converts People to TeamMember
  • CreateMap<Team, IEnumerable<TeamMember>>() converts Team to a list of TeamMember using a custom converter
Custom Converter
C#
public class TeanToTeamMemberListConverter : 
             ITypeConverter<Team, IEnumerable<TeamMember>>
{
    public IEnumerable<TeamMember> Convert
    (Team source, IEnumerable<TeamMember> destination, ResolutionContext context)
    {
        /*first mapp from People, then from Team*/
        foreach (var model in source.Members.Select
                (e => context.Mapper.Map<TeamMember>(e)))
        {
            context.Mapper.Map(source, model);
            yield return model;
        }

        /*first mapp from Team, then from People*/
        //foreach (var member in source.Members)
        //{
        //    var model = context.Mapper.Map<TeamMember>(source);
        //    context.Mapper.Map(member, model);
        //    yield return model;
        //}
    }
}

The converter is using previously configured Team to TeamMember and People to TeamMember mappings.

Using Mapper

C#
[HttpPost("[action]")]
public IEnumerable<TeamMember> ComplexObjectToList([FromBody] Team team)
{
    return Mapper.Map<IEnumerable<TeamMember>>(team);
}

List to Object

Here, we will convert a IEnumerable<TeamMember> to IEnumerable<Team>. TeamMember is a plain POCO model. Team is a complex model, which contains nested List<People> property and other properties. 

Model

Source Model
C#
public class TeamMember
{
    public int TeamId { get; set; }
    public string TeamName { get; set; }
    public int PeopleId { get; set; }
    public string PeopleName { get; set; }
}
Destination Object
C#
public class Team
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<People> Members { get; set; }
}

public class People
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Mapp Settings

C#
CreateMap<TeamMember, Team>()
    .ForMember(d => d.Id, opt => opt.MapFrom(s => s.TeamId))
    .ForMember(d => d.Name, opt => opt.MapFrom(s => s.TeamName));
CreateMap<TeamMember, People>()
    .ForMember(d => d.Id, opt => opt.MapFrom(s => s.PeopleId))
    .ForMember(d => d.Name, opt => opt.MapFrom(s => s.PeopleName));
CreateMap<IEnumerable<TeamMember>, IEnumerable<Team>>()
    .ConvertUsing<TeamMemberListToTeamConverter>();
  • CreateMap<TeamMember, Team>() converts Team to TeamMember
  • CreateMap<TeamMember, People>() converts People to TeamMember
  • CreateMap<IEnumerable<TeamMember>, IEnumerable<Team>>() converts a list of TeamMember to a list of Team using a custom converter
Custom Converter
C#
public class TeamMemberListToTeamConverter : ITypeConverter<IEnumerable<TeamMember>, IEnumerable<Team>>
{
    public IEnumerable<Team> Convert(IEnumerable<TeamMember> source, IEnumerable<Team> destination, ResolutionContext context)
    {
        /*
        List<int> ids = new List<int>();
        foreach (var item in source)
        {
            int id = item.TeamId;
            if (ids.Contains(id))
            {
                continue;
            }
            var model = context.Mapper.Map<Team>(item);
            model.Members = new List<People>();
            foreach (var people in source.Where(x => x.TeamId == model.Id && x.TeamName == model.Name))
            {
                model.Members.Add(context.Mapper.Map<People>(people));
            }
            ids.Add(id);
            yield return model;
        }
        */

        var teams = source.DistinctBy(m => new { m.TeamId, m.TeamName }).Select(member => context.Mapper.Map<Team>(member));
        foreach (var team in teams)
        {
            team.Members = new List<People>();
            foreach (var member in source.Where(m => m.TeamId == team.Id && m.TeamName == team.Name))
            {
                team.Members.Add(context.Mapper.Map<People>(member));
            }
            yield return team;
        }
    }
}

The converter is using previously configured TeamMember to Team and TeamMember to People mappings.

Using Mapper

C#
[HttpPost("[action]")]
public IEnumerable<Team> 
       ListToComplexObjectList([FromBody] IEnumerable<TeamMember> list)
{
    return Mapper.Map<IEnumerable<Team>>(list);
}

What's Next?

  • Conversion based on language preference

About Code Sample

  • Visual Studio 2022 Solution
  • ASP.NET 6, Web API project
  • This example is also tested in 5, 3.1

History

  • 27th July, 2022: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)