Back to: ASP.NET Core Web API Tutorials
Automapper Null Substitution in ASP.NET Core Web API
In this article, I will discuss Automapper Null Substitution with Simple and Complex Types in ASP.NET Core Web API Application with Examples. Please read our previous article discussing How to Ignore Property Mapping using Automapper in ASP.NET Core Web API Application with Examples.
Automapper Null Substitution in ASP.NET Core Web API
In the context of using AutoMapper in an ASP.NET Core Web API project, null substitution is a feature that allows you to define a default value for a destination property if the corresponding source property is null. That means it allows us to specify a default value that should be used when a source property is null during the mapping process.
This can be useful in scenarios where you want to ensure that the API consumers receive a meaningful default value instead of a null, which could potentially lead to errors or misunderstandings on the client side.
That means the Null Substitution allows us to supply an alternate value for a destination member if the source value is null. We need to use the Automapper NullSubstitute() method to substitute the null value.
Example to Understand Automapper Null Substitution in ASP.NET Core Web API
Let us understand how to use the Automapper NullSubstitute() method in the ASP.NET Core Web API Application with an example. Let us first create the following Employee and EmployeeDTO:
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? Address { get; set; } public string? CreatedBy { get; set; } public DateTime? CreatedOn { get; set; } } }
EmployeeDTO:
namespace AutomapperDemo.Models { public class EmployeeDTO { public int Id { get; set; } public string Name { get; set; } public string Department { get; set; } public string Address { get; set; } public string CreatedBy { get; set; } public DateTime CreatedOn { get; set; } } }
Business Requirement:
So, our business requirement is that if the Address Property Value is null in the Source Object, then we need to store N/A in the Address property in the destination object. Similarly, if the CreatedBy property is null, we need to store the System as its value. Finally, if the CreatedOn source property value is null, then we need to return the current date and time.
For these to be implemented, we need to use the NullSubstitute() method. 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() { // Configure mapping from Employee to EmployeeDTO CreateMap<Employee, EmployeeDTO>() //Storing N/A in the destination Address Property, if Source Address is NULL .ForMember(dest => dest.Address, act => act.NullSubstitute("N/A")) //Storing System in the destination CreatedBy Property, if Source CreatedBy is NULL .ForMember(dest => dest.CreatedBy, act => act.NullSubstitute("System")) //Storing Current Date and Time in the destination CreatedOn Property, if Source CreatedOn is NULL .ForMember(dest => dest.CreatedOn, act => act.NullSubstitute(DateTime.Now)); } } }
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 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", Address = "BBSR", CreatedBy=null, CreatedOn=null }, new Employee(){Id = 2, Name="Anurag", Department="HR", Address = null, CreatedBy=null, CreatedOn=DateTime.Now }, new Employee(){Id = 3, Name="Priyanla", Department="HR", Address = null, CreatedBy="Admin", CreatedOn=null } }; 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:
Automapper Null Substitution with Complex Types in ASP.NET Core Web API
Mapping configuration with null substitution for complex types in AutoMapper involves specifying how AutoMapper should handle null values when mapping properties of complex types from a source object to a destination object.
When mapping complex types, you might encounter situations where you want to substitute null values in the source object with a default instance of the complex type in the destination object. This ensures that the destination object’s properties are not left null, which can be useful when you want to avoid null reference exceptions or when the destination object expects specific properties to always be instantiated.
Consider that you have complex types as properties and want to substitute null complex objects with new instances. Let us understand this with an example. Please create the following models and DTOs.
Address
namespace AutomapperDemo.Models { public class Address { public string? City { get; set; } public string? State { get; set; } public string? Country { get; set; } } }
Employee
namespace AutomapperDemo.Models { public class Employee { public int Id { get; set; } public string Name { get; set; } public string Department { get; set; } public Address? Address { get; set; } public string? CreatedBy { get; set; } public DateTime? CreatedOn { get; set; } } }
AddressDTO
namespace AutomapperDemo.Models { public class AddressDTO { public string City { get; set; } public string State { get; set; } public string Country { get; set; } } }
EmployeeDTO
namespace AutomapperDemo.Models { public class EmployeeDTO { public int Id { get; set; } public string Name { get; set; } public string Department { get; set; } public AddressDTO Address { get; set; } public string CreatedBy { get; set; } public DateTime CreatedOn { get; set; } } }
Mapping Configuration with Null Substitution for Complex Types in ASP.NET Core Web API:
Use the ForMember method to specify the behavior for a particular property. Within this method, you can use NullSubstitute to define a default value when the source property is null. However, NullSubstitute is typically used for simple types. We need to use conditional mapping for complex types to achieve null substitution. This might involve checking if the source property is null and then setting the destination property to a new complex-type instance.
Whatever null substitution we have done in our previous example, the same one will do. But this time, when the complex Address property is null, we need to create a new AddressDTO object and initialize the City, State, and Country values with NA. To do so, please modify the MyMappingProfile class as follows:
using AutoMapper; namespace AutomapperDemo.Models { public class MyMappingProfile : Profile { public MyMappingProfile() { // Configure mapping between Address and AddressDTO CreateMap<Address, AddressDTO>(); // Configure mapping from Employee to EmployeeDTO CreateMap<Employee, EmployeeDTO>() //Storing N/A in the destination AddressDTO Object Properties, if Source Address is NULL .ForMember(dest => dest.Address, opt => opt.MapFrom(src => src.Address ?? new Address() { City = "NA", State = "NA", Country = "NA" })) //Storing System in the destination CreatedBy Property, if Source CreatedBy is NULL .ForMember(dest => dest.CreatedBy, act => act.NullSubstitute("System")) //Storing Current Date and Time in the destination CreatedOn Property, if Source CreatedOn is NULL .ForMember(dest => dest.CreatedOn, act => act.NullSubstitute(DateTime.Now)); } } }
In the above code, the ForMember and MapFrom methods are used to check if the source Employee object Address is null and, if so, instantiate a new AddressDTO object for the EmployeeDTO destination object. This approach ensures that complex types are substituted with a default instance rather than left null.
Using Automapper in a Controller
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", Address =null, CreatedBy=null, CreatedOn=null }, new Employee(){Id = 2, Name="Anurag", Department="HR", Address = new Address(){City="BBSR", State="Odisha", Country="India"}, CreatedBy=null, CreatedOn=DateTime.Now }, new Employee(){Id = 3, Name="Priyanla", Department="HR", Address = null, CreatedBy="Admin", CreatedOn=null } }; 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:
In the next article, I will discuss AutoMapper Advanced Concepts in ASP.NET Core Web API with Examples. In this article, I explain Automapper Null Substitution with Simple and Complex Types in ASP.NET Core Web API with Examples. I hope you enjoy this article, “Automapper Null Substitution in ASP.NET Core Web API.”