AutoMapper Complex Mapping in C#

AutoMapper Complex Mapping in C# with Examples

In this article, I am going to discuss the AutoMapper Complex Mapping in C# with some examples. Please read our previous article before proceeding to this article where we discussed the basics of Automapper in C# with some simple examples. At the end of this article you will understand what is AutoMapper Complex Mapping and when and how to use AutoMapper Complex Mapping in C# with examples.

What is AutoMapper Complex Mapping in C#?

When both the type involved in the mapping contains properties of the complex type then in such scenarios we need to use the AutoMapper Complex Mapping in C#. Let us understand the AutoMapper Complex Mapping with an example. We are going to use the following four classes for this demo.

AutoMapper Complex Mapping in C#

Business Requirement:

Our requirement is to map the Employee object to EmployeeDTO object. To make this demo simple, here we created both the classes with the same property names. But the thing that we need to keep in mind here is, we created the address property as a complex type. Then we are creating a static method i.e. InitializeAutomapper where we write the mapping code as shown in the below image.

Initialize Automapper in C#

Below is the complete code.
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Step1: Create and populate the Employee object
            Address empAddres = new Address()
            {
                City = "Mumbai",
                Stae = "Maharashtra",
                Country = "India"
            };

            Employee emp = new Employee
            {
                Name = "James",
                Salary = 20000,
                Department = "IT",
                address = empAddres
            };

            var mapper =InitializeAutomapper();
            var empDTO = mapper.Map<EmployeeDTO>(emp);
            
            Console.WriteLine("Name:" + empDTO.Name + ", Salary:" + empDTO.Salary + ", Department:" + empDTO.Department);
            Console.WriteLine("City:" + empDTO.address.City + ", State:" + empDTO.address.Stae + ", Country:" + empDTO.address.Country);
            Console.ReadLine();
        }
        
        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {             
                cfg.CreateMap<Employee, EmployeeDTO>();
            });

            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public Address address { get; set; }
    }
    public class EmployeeDTO
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public AddressDTO address { get; set; }
    }
    public class Address
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }
    public class AddressDTO
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }
}

Now, when you run the application, you will get the following runtime exception.

Missing type map configuration or unsupported mapping

Now, if you go the inner exception and check the message property, then it clearly shows that mapping type configuration is missing for Address and AddresDTO. This is because in our mapper configuration, we have specified the Mapper for Employee and EmployeeDTO but not for Address and AddressDTO type.

Missing Type configuration in AutoMapper

How to solve the above Problem?

In order to solve the above problem, you need to configure the mapping between the Address and AddressDTO, before the Employee and EmployeeDTO Mapping. So, change the InitializeAutomapper method as shown below.

AutoMapper Complex Mapping in C#

With the above changes in place, now, if you run the application and then you will get the output as expected as shown in the below image.

AutoMapper with Nested Types

What happen if we changes the complex type property name involved in automapper? 

Let us understand this with an example. Let’s change the complex property address to addressDTO of the EmployeeDTO class as shown below.

AutoMapper with Nested Types

Below is the complete code.
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Address empAddres = new Address()
            {
                City = "Mumbai",
                Stae = "Maharashtra",
                Country = "India"
            };

            Employee emp = new Employee
            {
                Name = "James",
                Salary = 20000,
                Department = "IT",
                address = empAddres
            };

            var mapper =InitializeAutomapper();
            var empDTO = mapper.Map<EmployeeDTO>(emp);

            Console.WriteLine("Name:" + empDTO.Name + ", Salary:" + empDTO.Salary + ", Department:" + empDTO.Department);
            Console.WriteLine("City:" + empDTO.addressDTO.City + ", State:" + empDTO.addressDTO.Stae + ", Country:" + empDTO.addressDTO.Country);
            Console.ReadLine();
        }
        
        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Address, AddressDTO>();
                cfg.CreateMap<Employee, EmployeeDTO>();
            });

            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public Address address { get; set; }
    }

    public class EmployeeDTO
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public AddressDTO addressDTO { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }

    public class AddressDTO
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }
}

Now run the application. It should give you the following error.

What happen if we changes the complex type property name involved in automapper

This is because the property name for addressDTO is not found in the Employee object. So we get the null reference error. 

How to solve the above problem?

To solve the above issue we need to map the address property to addressDTO property in the mapper configuration as shown in the below image.

Complex Mapping using AutoMapper in C#

With the above changes in automapper config, now run the application and it will give you the result as expected.

What happen if the Complex type property names are different?

Let us understand this with an example. Let’s modify the property names in the AddressDTO class as shown below.

AutoMapper with Nested Types

Below is the complete example.
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Address empAddres = new Address()
            {
                City = "Mumbai",
                Stae = "Maharashtra",
                Country = "India"
            };

            Employee emp = new Employee
            {
                Name = "James",
                Salary = 20000,
                Department = "IT",
                address = empAddres
            };

            var mapper =InitializeAutomapper();
            var empDTO = mapper.Map<EmployeeDTO>(emp);

            Console.WriteLine("Name:" + empDTO.Name + ", Salary:" + empDTO.Salary + ", Department:" + empDTO.Department);
            Console.WriteLine("City:" + empDTO.addressDTO.EmpCity + ", State:" + empDTO.addressDTO.EmpStae + ", Country:" + empDTO.addressDTO.Country);
            Console.ReadLine();
        }
        
        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Address, AddressDTO>();
                cfg.CreateMap<Employee, EmployeeDTO>()
                .ForMember(dest => dest.addressDTO, act => act.MapFrom(src => src.address));
            });

            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public Address address { get; set; }
    }

    public class EmployeeDTO
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public AddressDTO addressDTO { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }

    public class AddressDTO
    {
        public string EmpCity { get; set; }
        public string EmpStae { get; set; }
        public string Country { get; set; }
    }
}

When you run the application, it will not give you any error, but it will not map the City and State property as shown in the below output.

AutoMapper with Nested Types

This is because we mapped the Address object with the AddressDTO object, but we had not mapped the City and State properties with EmpCity and EmpState properties. Let’s map the above two properties and see what happens. To map the above two properties we need to change the InitializeAutomapper class as shown below.

AutoMapper with Nested Types in C#

The complete code is given below:
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Address empAddres = new Address()
            {
                City = "Mumbai",
                Stae = "Maharashtra",
                Country = "India"
            };

            Employee emp = new Employee
            {
                Name = "James",
                Salary = 20000,
                Department = "IT",
                address = empAddres
            };

            var mapper =InitializeAutomapper();
            var empDTO = mapper.Map<EmployeeDTO>(emp);

            Console.WriteLine("Name:" + empDTO.Name + ", Salary:" + empDTO.Salary + ", Department:" + empDTO.Department);
            Console.WriteLine("City:" + empDTO.addressDTO.EmpCity + ", State:" + empDTO.addressDTO.EmpStae + ", Country:" + empDTO.addressDTO.Country);
            Console.ReadLine();
        }
        
        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Address, AddressDTO>()
                .ForMember(dest => dest.EmpCity, act => act.MapFrom(src => src.City))
                    .ForMember(dest => dest.EmpStae, act => act.MapFrom(src => src.Stae)); ;
                cfg.CreateMap<Employee, EmployeeDTO>()
                .ForMember(dest => dest.addressDTO, act => act.MapFrom(src => src.address));
            });

            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public Address address { get; set; }
    }

    public class EmployeeDTO
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public AddressDTO addressDTO { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }

    public class AddressDTO
    {
        public string EmpCity { get; set; }
        public string EmpStae { get; set; }
        public string Country { get; set; }
    }
}

With the above changes in place, now run the application and see the output as expected as shown in the below image.

AutoMapper Complex Mapping in C#

In the next article, we will discuss how to map complex type to primitive types using automapper in C#. In this article, I try to explain the AutoMapper Complex Mapping in C# with some examples. I hope this AutoMapper Complex Mapping in C# article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

2 thoughts on “AutoMapper Complex Mapping in C#”

Leave a Reply

Your email address will not be published. Required fields are marked *