Mapping Complex Type to Primitive Type using AutoMapper in ASP.NET Core Web API

Mapping Complex Type to Primitive Type using AutoMapper

In this article, I will discuss Mapping Complex Type to Primitive Type using AutoMapper in ASP.NET Core Web API Application with Examples. Please read our previous article discussing AutoMapper Complex Mapping in ASP.NET Core Web API with Examples.

How to Map Complex Type to Primitive Type using AutoMapper?

Mapping Complex Types to Primitive Types using AutoMapper in ASP.NET Core Web API is a common scenario, especially when you want to transform data from your domain models (Complex Types) to simpler, more client-friendly models (DTOs or view models that are often primitive types or simpler objects). AutoMapper simplifies this process by automatically handling the mapping between source and destination types based on conventions, configurations, and rules.

Example to Understand Complex Type to Primitive Type using AutoMapper in ASP.NET Core Web API:

When one class contains primitive types, or you can say simple types like integer, string, bool, etc., and the other class contains complex types involved in the mapping, then in such scenarios, we need to Map the Complex Type to the Primitive Types.

When mapping from a complex type to a primitive type, AutoMapper uses a process to extract a value from the complex type’s property and map it to a primitive type property. A complex type is an object that has properties of its own, while a primitive type is a basic data type such as an integer, string, boolean, etc.

Let us understand how to map Complex type to Primitive Type using AutoMapper in ASP.NET Core Web API with an example. Here in this demo, we are going to use the following three classes (User, Address, and UserDTO).

Address Model:

Create a class file named Address.cs, and then copy and paste the following code. This model is going to store the Address of a User.

namespace AutomapperDemo.Models
{
    public class Address
    {
        public int AddressId { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Country { get; set; }
        public int UserId { get; set; }
    }
}
User Model:

Create a class file named User.cs, and then copy and paste the following code. This model is going to store the User information.

namespace AutomapperDemo.Models
{
    public class User
    {
        public int UserId { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public Address Address { get; set; }
    }
}
UserDTO 

Create a class file named UserDTO.cs and then copy and paste the following code. This model is going to store both the User and the address of the user. This model is going to be used for data transformation and will be used by the client to communicate with our APIs.

namespace AutomapperDemo.Models
{
    public class UserDTO
    {
        public int UserId { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Country { get; set; }
    }
}
Mapping Complex Type to Primitive Type using AutoMapper:

To map the Complex Type to the Primitive Types, we need to use the ForMember method of AutoMapper, and we also need to specify the source and target properties. Here, we need to map the City, State, and Country properties of the Address object (Address property of User Object) to the City, State, and Country properties of the UserDTO class.

Next, create a class file with the name MyMappingProfile.cs and copy and paste the following code. Here, as you can see, we are mapping the City, State, and Country properties of the Address object (Address property of User Object) to the City, State, and Country properties of the UserDTO object. Here, the source is the User object, and the destination is the UserDTO object, and we are mapping from the source User to the destination UserDTO object:

using AutoMapper;
namespace AutomapperDemo.Models
{
    public class MyMappingProfile : Profile
    {
        public MyMappingProfile()
        {
            //Configure the Mappings
            CreateMap<User, UserDTO>()
               //Provide Mapping Information for City Property
               .ForMember(dest => dest.City, act => act.MapFrom(src => src.Address.City))
               //Provide Mapping Information for State Property
               .ForMember(dest => dest.State, act => act.MapFrom(src => src.Address.State))
               //Provide Mapping Information for Country Property
               .ForMember(dest => dest.Country, act => act.MapFrom(src => src.Address.Country));
        }
    }
}

As shown in the above code, we mapped each property from the complex type (Address) of the source object (User) to the correspondent properties of the destination object (UserDTO).

Register AutoMapper in Program.cs

Register AutoMapper and profiles with the dependency injection container in Program.cs class file. So, please add the following statement within the Program class. This configuration tells AutoMapper to scan the assembly (or assemblies) for classes that inherit from Profile and automatically register them.

builder.Services.AddAutoMapper(typeof(Program).Assembly);

Implementing the Mapping in a Controller

Now, implement a controller that uses AutoMapper to return a list of users with their addresses. So, create an Empty API Controller named User and then copy and paste the following code:

using AutoMapper;
using AutomapperDemo.Models;
using Microsoft.AspNetCore.Mvc;

namespace AutomapperDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private readonly IMapper _mapper;

        public UserController(IMapper mapper)
        {
            _mapper = mapper;
        }

        private List<User> listUsers = new List<User>()
        {
           new User { UserId = 1, Name="Pranaya", Email="Pranaya@Example.come",
               Address = new Address()
               {
                  Country = "India",
                  State = "Odisha",
                  City = "BBSR",
                  AddressId = 1001,
                  UserId = 1,
               }
           },
           new User { UserId = 2, Name="Priyanka", Email="Priyanka@Example.come",
               Address = new Address()
               {
                  Country = "India",
                  State = "Maharashtra",
                  City = "Mumbai",
                  AddressId = 1002,
                  UserId = 2,
               }
           }
        };

        [HttpGet]
        public ActionResult<List<CategoryDTO>> GetAllUsers()
        {
            List<UserDTO> users = _mapper.Map<List<UserDTO>>(listUsers);
            return Ok(users);
        }
    }
}

Now, run the application and access the above endpoint (/api/user) using a GET HTTP Request, and you should get the output as expected, as shown in the below image.

Mapping Complex Type to Primitive Type using AutoMapper in ASP.NET Core Web API

Mapping Primitive Properties to a Complex Type using Automapper in ASP.NET Core Web API:

Mapping primitive types to a complex type using AutoMapper in an ASP.NET Core Web API involves transforming simple, often scalar, data into a more structured object model. This scenario can arise when you have multiple simple types as inputs that need to be combined into a single complex object.

Suppose we have a scenario where an API endpoint receives simple fields from a service, and these fields need to be combined into a complex object. For example, you might receive separate strings representing a user’s first name, last name, and address details, which you then want to map to a User object with nested Address information. Let us proceed and understand how we can implement this using Automapper in ASP.NET Core Web API.

Let us modify the User model class as follows. Now, you can see we have removed the Address Complex property, and we have added the City, State, and Country Primitive properties.

namespace AutomapperDemo.Models
{
    public class User
    {
        public int UserId { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Country { get; set; }
    }
}

Now, we want to map the City, State, and Country Properties of the source (User) object to the Address property of the destination (UserDTO) object. So, let us add the following AddressDTO.cs class file and then copy and paste the following code.

namespace AutomapperDemo.Models
{
    public class AddressDTO
    {
        public string City { get; set; }
        public string State { get; set; }
        public string Country { get; set; }
    }
}

Next, modify the UserDTO class as follows. Here, you can see we have removed the primitive City, State, and Country properties and added the Complex AddressDTO property.

namespace AutomapperDemo.Models
{
    public class UserDTO
    {
        public int UserId { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public AddressDTO Address { get; set; }
    }
}
Modifying MyMappingProfile Class

Now, we need to Map the Primitive Properties (i.e., City, State, and Country) of the Source Object (i.e., User) to a Complex Property (i.e., AddressDTO) of the Destination Object (i.e., UserDTO). To do so, modify the MyMappingProfile class as follows.

using AutoMapper;
namespace AutomapperDemo.Models
{
    public class MyMappingProfile : Profile
    {
        public MyMappingProfile()
        {
            //Configure the Mappings
            CreateMap<User, UserDTO>()
               .ForMember(dest => dest.Address, act => act.MapFrom(src => new AddressDTO()
               {
                   City = src.City,
                   State = src.State,
                   Country = src.Country
               }));
        }
    }
}

This mapping configuration tells AutoMapper that when mapping from User to UserDTO, it should create a new AddressDTO object for the Address property of UserDTO, using the City, State, and Country fields from User. Here, we project an object (AddressDTO type) using the MapForm option, and City, State, and Country Values come from the Source object.

Modifying the User Controller:

Next, modify the User Controller as follows.

using AutoMapper;
using AutomapperDemo.Models;
using Microsoft.AspNetCore.Mvc;

namespace AutomapperDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private readonly IMapper _mapper;

        public UserController(IMapper mapper)
        {
            _mapper = mapper;
        }

        private List<User> listUsers = new List<User>()
        {
           new User { UserId = 1, Name="Pranaya", Email="Pranaya@Example.come", Country = "India", State = "Odisha",City = "BBSR" },
           new User { UserId = 2, Name="Priyanka", Email="Priyanka@Example.come", Country = "India", State = "Maharashtra", City = "Mumbai"}
        };

        [HttpGet]
        public ActionResult<List<CategoryDTO>> GetAllUsers()
        {
            List<UserDTO> users = _mapper.Map<List<UserDTO>>(listUsers);
            return Ok(users);
        }
    }
}

Now, with the above changes in place, run the application and access the above endpoint (/api/user) using a GET HTTP Request, and you should get the output as expected, as shown in the image below.

Mapping Primitive Properties to a Complex Type using Automapper in ASP.NET Core Web API

In the next article, I will discuss AutoMapper Reverse Mapping in ASP.NET Core Web API with Examples. In this article, I explain Mapping Complex Types to Primitive Types using AutoMapper in ASP.NET Core Web API with Examples. I hope you enjoy this article, “Mapping Complex Types to Primitive Types using AutoMapper in ASP.NET Core Web API.”

Leave a Reply

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