Ignore Property Mapping using Automapper in ASP.NET Core Web API

How to Ignore Property Mapping using Automapper in ASP.NET Core Web API

In this article, I will discuss How to Ignore Property Mapping using Automapper in ASP.NET Core Web API Application with Examples. Please read our previous article discussing the Differences Between Automapper Condition, PreCondition, and PostCondition in ASP.NET Core Web API with Examples.

Ignore Property Mapping using Automapper in ASP.NET Core Web API.

Ignoring a property mapping in AutoMapper is a common requirement when you do not want to map specific properties from the source object to the destination object. AutoMapper provides a straightforward way to achieve this using the ForMember method and the Ignore method on the mapping configuration.

Sometimes, you might want to exclude specific properties from being mapped to avoid unnecessary data exposure or simply because those properties do not have equivalent counterparts in the target object.

By default, AutoMapper tries to map all the properties from the source to the destination type when the names of both the source and destination type are the same. You can configure AutoMapper to ignore specific properties by using the ForMember() method in your mapping profile and chaining it with the Ignore() method.

Automapper Ignore Method

The Ignore method explicitly ignores a particular property during the mapping process. This is useful when you do not want AutoMapper to attempt to map a specific property from the source to the destination object, either because the property does not exist on the destination or because you’re handling the property’s value through some other means.

Syntax:
CreateMap<Source, Destination>()
.ForMember(dest => dest.PropertyToIgnore, opt => opt.Ignore());

AutoMapper will not attempt to map PropertyToIgnore from the Source object to the Destination object.

Here are real-time examples and scenarios where you might want to ignore property mappings and how to achieve that using the AutoMapper Ignore method.

Ignoring Sensitive Information

Consider a User entity in your domain model that includes sensitive information such as passwords or security tokens. When mapping this User entity to a UserDTO for API responses, you would want to ignore these sensitive properties to prevent exposing them to the client. Let us understand this with an example. First, create the following Model and DTO. Both classes have the same number, same name, and same types of properties.

User Model:

Create a class file named User.cs, then copy and paste the following code.

namespace AutomapperDemo.Models
{
    public class User
    {
        public int Id { get; set; }
        public string Username { get; set; }
        public string Password { get; set; } // Sensitive Information
        public string SecurityToken { get; set; } // Sensitive Information
    }
}
UserDTO:

Create a class file named UserDTO.cs, and then copy and paste the following code.

namespace AutomapperDemo.Models
{
    public class UserDTO
    {
        public int Id { get; set; }
        public string Username { get; set; }
        public string Password { get; set; } 
        public string SecurityToken { get; set; } 
    }
}
Mapping Profile Configuration

Our Business Requirement is not to map the Password and SecurityToken Properties, i.e., we need to Ignore the Password and SecurityToken Properties while mapping between these objects. To do so, we need to use the Ignore Method with the Password and SecurityToken Properties of the destination type while doing the mapper configuration.

Create a mapping profile that defines the mapping between User and UserDTO. So, create a class file with the names MyMappingProfile.cs and copy and paste the following code. Here, using the ForMember method, we are calling the Ignore method for the destination Password and SecurityToken Properties, which will Ignore these two properties while doing the Mapping:

using AutoMapper;
namespace AutomapperDemo.Models
{
    public class MyMappingProfile : Profile
    {
        public MyMappingProfile()
        {
            CreateMap<User, UserDTO>()
            .ForMember(dest => dest.Password, opt => opt.Ignore())
            .ForMember(dest => dest.SecurityToken, opt => opt.Ignore());
        }
    }
}
Register AutoMapper in Program.cs

Register AutoMapper and profiles with the dependency injection container in the 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);

Using Automapper in a Controller

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;
        }

        [HttpGet("{Id}")]
        public IActionResult GetUser(int Id)
        {
            var user = new User()
            {
                Id = Id,
                Username = "Test",
                Password = "123@ABC",
                SecurityToken = Guid.NewGuid().ToString(),
            };

            var userDTO = _mapper.Map<UserDTO>(user);
            
            return Ok(userDTO);
        }
    }
}
Testing the API:

Let us test the above endpoint using Postman and see the results.

API: Fetch the User Details

URL: api/User/1001

Method: GET

Using Postman:

How to Ignore Property Mapping using Automapper in ASP.NET Core Web API

As you can see in the above response, the Password and SecurityToken Properties value is null even though the Password and SecurityToken Properties for the Source type have value. So, the AutoMapper Ignore() method is used when you want to ignore the property in the mapping completely.

How Do We Ignore Multiple Properties using Attribute in AutoMapper?

In our previous example, we saw how to use the ignore method with two properties. This is fine if you are Ignoring one or two properties. However, it will become tedious if you want to ignore multiple properties from mapping. If that is your requirement, consider creating an extension class that will Ignore the properties based on the attribute specified in the model.

Create a NoMap Attribute Class

Create a class file named NoMapAttribute.cs, then copy and paste the following code. Here, you can see the NoMapAttribute class is inherited from the System.Attribute class. Now, we can use this class as an attribute.

namespace AutomapperDemo.Models
{
    public class NoMapAttribute:System.Attribute
    {
    }
}
Decorate the Properties with the NoMap Attribute

We need to decorate the NoMap Attribute with the source type properties we don’t want to map with the destination type. For example, suppose you don’t want to map the Password and SecurityToken Properties. In that case, you need to decorate the NoMap attribute with the Password and SecurityToken Properties of the User class. So, modify the User class as follows.

namespace AutomapperDemo.Models
{
    public class User
    {
        public int Id { get; set; }
        public string Username { get; set; }
        [NoMap]
        public string Password { get; set; } // Sensitive Information
        [NoMap]
        public string SecurityToken { get; set; } // Sensitive Information
    }
}
Creating an Extension Method

Create a class file named IgnoreNoMapExtensions.cs, and copy and paste the following code. This will be a static class, and within this static class, we are creating one static method and passing the parameter as IMappingExpression using this keyword. Within this method, we check whether the property is decorated with the NoMap Attribute. If it is decorated with NoMap Attribute, we call the Ignore method.

using AutoMapper;
using System.ComponentModel;

namespace AutomapperDemo.Models
{
    public static class IgnoreNoMapExtensions
    {
        //Method is Generic and Hence we can use with any TSource and TDestination Type
        public static IMappingExpression<TSource, TDestination> IgnoreNoMap<TSource, TDestination>(
            this IMappingExpression<TSource, TDestination> expression)
        {
            //Fetching Type of the TSource
            var sourceType = typeof(TSource);

            //Fetching All Properties of the Source Type using GetProperties() method
            foreach (var property in sourceType.GetProperties())
            {
                //Get the Property Name
                PropertyDescriptor descriptor = TypeDescriptor.GetProperties(sourceType)[property.Name];
                
                //Check if Property is Decorated with the NoMapAttribute
                NoMapAttribute attribute = (NoMapAttribute)descriptor.Attributes[typeof(NoMapAttribute)];
                
                if (attribute != null)
                {
                    //If Property is Decorated with NoMap Attribute, call the Ignore Method
                    expression.ForMember(property.Name, opt => opt.Ignore());
                }
            }
            return expression;
        }
    }
}
Using the IgnoreNoMap Extension Method in Mapper Configuration

In the last step, we need to use the IgnoreNoMap method while defining the Mapping. So, modify the MyMappingProfile.cs as follows. Here, you can see that after the mapping, we are simply calling the IgnoreNoMap method. This IgnoreNoMap Extension method is generic and can be used with any other mapping if required.

using AutoMapper;
namespace AutomapperDemo.Models
{
    public class MyMappingProfile : Profile
    {
        public MyMappingProfile()
        {
            CreateMap<User, UserDTO>()
                .IgnoreNoMap();
        }
    }
}

With the above changes in place, run the application and access the endpoint (api/User/1001) using HTTP GET Request, and you should get the response as expected, as shown in the below image:

How Do We Ignore Multiple Properties using Attribute in AutoMapper?

How to Ignoring All Null Values During Update Operations

When updating an entity using PATCH or PUT requests, you might want to ignore null values from the DTO to prevent overwriting existing values with nulls in the database. Assuming you have a Product entity and a corresponding ProductDTO, and you only want to update properties that are explicitly set (not null) in the DTO. First, create the following Product Model and DTO.

Product Model:

Create a class file named Product.cs, then copy and paste the following code.

namespace AutomapperDemo.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}
ProductDTO:

Create a class file named ProductDTO.cs and copy and paste the following code.

namespace AutomapperDemo.Models
{
    public class ProductDTO
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public decimal? Price { get; set; }
    }
}
Configure AutoMapper

We need to configure AutoMapper to handle null values during mapping properly. Since AutoMapper does not have a built-in way to ignore nulls globally, we need to create a custom extension method for this purpose.

The following AutoMapperExtensions class introduces a method called IgnoreAllNull, which is designed to configure an AutoMapper mapping expression to ignore all source properties that have null values during the mapping process. So, create a class file named AutoMapperIgnoreNullExtensions.cs and then copy and paste the following code into it:

using AutoMapper;
namespace AutomapperDemo.Models
{
    public static class AutoMapperExtensions
    {
        public static IMappingExpression<TSource, TDestination> IgnoreAllNull<TSource, TDestination>(
            this IMappingExpression<TSource, TDestination> expression)
        {
            expression.ForAllMembers(options =>
            {
                options.Condition((src, dest, srcMember) => srcMember != null);
            });
            return expression;
        }
    }
}
Explanation
  • Static Class Definition: The AutoMapperExtensions class is static, meaning it cannot be instantiated. Its purpose is to contain static methods that can be called without creating an instance of the class.
  • IgnoreAllNull Method: This is an extension method for the IMappingExpression<TSource, TDestination> interface from AutoMapper. Extension methods allow you to add new methods to existing types without modifying them. Here, TSource is the source type being mapped from, and TDestination is the destination type being mapped to.
  • Method Signature:
      1. Before the first parameter, the “this” keyword indicates that this method extends IMappingExpression<TSource, TDestination>. This means that any instance of IMappingExpression<TSource, TDestination> will have access to this method.
      2. The method returns IMappingExpression<TSource, TDestination>, allowing for method chaining on mapping configurations.
  • Method Body: The body of IgnoreAllNull uses the ForAllMembers method to apply a condition to all members of the destination type during mapping.
      1. ForAllMembers takes an action that configures options for each member of the destination type.
      2. The options.Condition method is used to specify a condition that must be true for the mapping to occur for each member. The condition provided is a lambda function (src, dest, srcMember) => srcMember != null, which checks if the source member’s value is not null. This effectively tells AutoMapper to ignore mapping any source property with a null value, thus preventing null source values from overwriting non-null destination values.
Apply Configuration in Mapping Profile

Use the extension method in your AutoMapper profile to ignore null values during mapping. So, create a class file with the names MyMappingProfile.cs and copy and paste the following code.

using AutoMapper;
namespace AutomapperDemo.Models
{
    public class MyMappingProfile : Profile
    {
        public MyMappingProfile()
        {
            CreateMap<ProductDTO, Product>()
            .IgnoreAllNull();
        }
    }
}
Using AutoMapper for Update Operations

When performing the update operation in your service or controller, use AutoMapper to map the DTO to the entity. The custom extension method ensures that null values in the DTO do not overwrite existing values in the entity.

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

namespace AutomapperDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ProductController : ControllerBase
    {
        //Create a variable to holder mapper instance
        private readonly IMapper _mapper;

        //Framework will inject the instance using Constructor
        public ProductController(IMapper mapper)
        {
            //Initialize the variable with the injected mapper instance
            _mapper = mapper;
        }

        private List<Product> listProducts = new List<Product>()
        {
            new Product { Id = 1001, Name="Laptop", Price = 1000},
            new Product { Id = 1002, Name="Desktop", Price = 2000}
        };

        [HttpPut("{Id}")]
        public ActionResult<Product> UpdateProduct(int Id, ProductDTO productDTO)
        {
            var product = listProducts.FirstOrDefault(prd => prd.Id == Id);

            if (product == null)
            {
                return NotFound("Product Not Found");
            }

            // AutoMapper will ignore null values in productDTO during mapping
            _mapper.Map(productDTO, product);

            return Ok(product);
        }
    }
}
Testing the API:

Let us test the above endpoint using Postman and see the results.

API: Update Product by ID

URL: api/Product/1001

Method: PUT

{
  "id": 1001,
  "name": null,
  "price": 5000
}
Using Postman:

blank

Ignoring All Non-Existing Properties using Automapper in ASP.NET Core Web API

Ignoring all non-existing properties in AutoMapper can streamline your mapping configuration, especially when dealing with complex objects where you only want to map a subset of properties that actually exist in both source and destination types. This approach is particularly useful in scenarios where you wish to avoid manual configuration for each property that doesn’t have a corresponding match in the destination type.

You can configure AutoMapper in an ASP.NET Core Web API project to ignore all non-existing properties using the MemberList.None option. First, create the following Employee model:

namespace AutomapperDemo.Models
{
    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Department { get; set; }
        public string Position { get; set; }
        public decimal Salary { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Country { get; set; }
    }
}

Next, create the following EmployeeDTO model.

namespace AutomapperDemo.Models
{
    public class EmployeeDTO
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Department { get; set; }
        public string Position { get; set; }
        public decimal Salary { get; set; }
    }
}

As you can see, the EmployeeDTO does not include the City, State, and Country properties. So, we want to ignore these properties while mapping between Employee and EmployeeDTO using Automapper. To do so, please modify the MyMappingProfile class as follows:

using AutoMapper;
namespace AutomapperDemo.Models
{
    public class MyMappingProfile : Profile
    {
        public MyMappingProfile()
        {
            // Configure mapping from Employee to EmployeeDTO
            // MemberList.None: Check neither source nor destination members, skipping validation
            CreateMap<Employee, EmployeeDTO>(MemberList.None);
        }
    }
}

As you can see here, we are using MemberList.None which will not Check source nor destination members, skipping validation. So, if you to the definition of MemberList enum, then you will see the following:

Ignoring All Non-Existing Properties using Automapper in ASP.NET Core Web API

The meaning of each enum property is as follows:

  • None: Specifies that no validation should be performed on the destination member list. AutoMapper does not check whether all destination-type members are mapped when you choose this option. This is useful when you’re only interested in mapping a subset of members and want to ignore unmapped members without receiving any warnings or exceptions.
  • Source: AutoMapper should validate that all source type members are mapped to the destination type. This option is helpful in ensuring that no data is lost in the mapping process. It helps to catch scenarios where a source member might have been left unmapped.
  • Destination: AutoMapper should validate that all destination-type members have a corresponding source member mapped to them. This is particularly useful when you want to ensure completeness in your destination model, ensuring that every member of the destination type has been considered in the mapping.

Next, modify the Employee Controller as follows:

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

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

        public List<Employee> listEmployees = new List<Employee>()
        {
            new Employee(){Id = 1, Name="Pranaya", Department="IT", Position = "DBA", Salary=1000, 
                City="BBSR", State="Odisha", Country="India" },
            new Employee(){Id = 1, Name="Anurag", Department="HR", Position = "Developer", Salary=2000,
                City="CTC", State="Odisha", Country="India" }
        };

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

        [HttpGet("{Id}")]
        public ActionResult<EmployeeDTO> GetEmployee(int Id)
        {
            var employee = listEmployees.FirstOrDefault(emp => emp.Id == Id);
            if (employee == null)
            {
                return NotFound("Employee Not Found");
            }

            var employeeDTO = _mapper.Map<EmployeeDTO>(employee);

            return Ok(employeeDTO);
        }
    }
}
Testing the API:

Let us test the above endpoint using Postman and see the results.

API: Fetch the Employee Details

URL: api/Employee/1

Method: GET

Using Postman:

How to Ignore Property Mapping using Automapper in ASP.NET Core Web API with Examples

Use Cases for Automapper Ignore Method in ASP.NET Core Web API

The AutoMapper Ignore method is a powerful feature for configuring object-to-object mappings, allowing developers to exclude specific properties from being mapped. This capability can be crucial in various scenarios to ensure data integrity, optimize performance, and customize the mapping process to fit specific requirements. Here are several use cases where the Ignore method is particularly useful:

  • Preserving Destination Values: When updating an existing object with values from another object, it might be necessary to preserve specific properties of the destination object. For example, in a user profile update scenario, you might want to exclude the PasswordHash or CreationDate fields from being overwritten.
  • Read-Only Properties: If the destination class contains read-only properties or properties that should not be modified after the initial creation (e.g., EntityId, CreatedAt timestamp), using the Ignore method ensures these values remain unchanged.
  • Partial Updates: When implementing partial update APIs (e.g., PATCH in RESTful services), it might be necessary only to update properties that the client explicitly provided. Ignoring null or undefined properties in the source object can prevent unintentional overwrites of existing values.
  • Custom Initialization Logic: For properties that require custom initialization logic that AutoMapper cannot easily replicate, using the Ignore method allows you to manually set these properties after the mapping has occurred, providing greater control over the object’s state.
  • Security Considerations: In scenarios involving user input or external data sources, ignoring properties that should not be affected by such inputs can enhance security. This prevents unauthorized updates to sensitive fields like user roles, permissions, etc.

In the next article, I will discuss Automapper Null Substitution in ASP.NET Core Web API Application with Examples. In this article, I explain How to Ignore Property Mapping using Automapper in ASP.NET Core Web API with Examples. I hope you enjoy this article, “Ignore Property Mapping using Automapper in ASP.NET Core Web API.”

Leave a Reply

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