How to use profiles, reverse mapping, nested mapping, and other advanced operations of the open source object mapper AutoMapper Credit: Thinkstock AutoMapper is a convention-based, object-oriented mapper. An object-oriented mapper is one that transforms an input object into an output object of a different type. AutoMapper also can be used to map similar or dissimilar objects (i.e., objects having properties that may or may not be identical). We examined the basic features of AutoMapper in a previous article. In this article we’ll explore some of the advanced features of AutoMapper. Create an ASP.Net Core project in Visual Studio First off, let’s create a new ASP.Net Core project in Visual Studio. Note that you can create any project, i.e., MVC or even a Console Application, to work with AutoMapper. If Visual Studio 2019 is installed in your system, follow the steps outlined below to create a new ASP.Net Core project. Launch the Visual Studio IDE. Click on “Create new project.” In the “Create new project” window, select “ASP.Net Core Web Application” from the list of templates displayed. Click Next. In the “Configure your new project” window shown next, specify the name and location for the new project. Click Create. In the “Create New ASP.Net Core Web Application” window shown next, select .Net Core as the runtime and ASP.Net Core 2.2 (or later) from the drop-down menu at the top. Select “Web Application” as the project template to create a new ASP.Net Core web application. Ensure that the check boxes “Enable Docker Support” and “Configure for HTTPS” are unchecked as we won’t be using those features here. Ensure that Authentication is set to “No Authentication” as we won’t be using authentication either. Click Create. Now you should have a new ASP.Net Core project ready to go in Visual Studio. We’ll use this project in the subsequent sections of this article to illustrate a few advanced operations using AutoMapper. Install AutoMapper To start working with AutoMapper, you should install the necessary packages in your project. To do this, you can use the following commands at the NuGet Package Manager Console window: Install-Package AutoMapper Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection Assuming the installation is successful, you are all set to use AutoMapper in your project. Configure AutoMapper Once AutoMapper has been successfully installed, you can configure it by calling the AddAutoMapper method on the IServiceCollection instance. public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion (CompatibilityVersion.Version_2_2); services.AddAutoMapper(); } Use profiles to specify mapping information in AutoMapper You can organize your mapping collections using profiles. To create a profile, you need to create a class that extends the Profile class of the AutoMapper library. You can then add the necessary mapping configuration information to the constructor of the class you just created. The CreateMap method is used to create mapping between two types. The following class shows how you can create a class named AuthorProfile by extending the Profile class and specifying mapping information. public class AuthorProfile : Profile { public AuthorProfile() { CreateMap<AuthorModel, AuthorDTO>(); } } Use the ReverseMap() method in AutoMapper Note that the example above is a one-way mapping. Similarly, suppose you have defined a one-way mapping using the CreateMap method as shown in the code snippet below. AutoMapper.Mapper.CreateMap<Author, AuthorModel>(); You can now map an instance of the Author class to an AuthorModel as shown below. var authorModel = AutoMapper.Mapper.Map<AuthorModel>(author); Now suppose you would like to map the AuthorModel instance back to an Author instance. You might try using the following code. var author = AutoMapper.Mapper.Map<Author>(authorModel); However, note that this would throw a runtime exception. The exception occurs because the AutoMapper runtime lacks the knowledge needed to perform this mapping. One way to achieve this reverse mapping is by recreating the mapping from the scratch. A simpler and better way is by using the ReverseMap method off the CreateMap method, as shown in the code snippet below. AutoMapper.Mapper.CreateMap<Author, AuthorModel>().ReverseMap(); Use the ForMember() and MapFrom() methods in AutoMapper This next example will use the AuthorModel and AuthorDTO classes from my previous article on AutoMapper. You can refer to that article here. The following code snippet illustrates how you can map objects of the AuthorModel and AuthorDTO classes. var author = new AuthorModel(); author.Id = 1; author.FirstName = "Joydip"; author.LastName = "Kanjilal"; author.Address = "Hyderabad"; var authorDTO = _mapper.Map<AuthorDTO>(author); Now suppose the property named Address has been changed to Address1 in the AuthorModel class. public class AuthorModel { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Address1 { get; set; } } You can then update the mapping information in the AuthorProfile class as shown below. public class AuthorProfile : Profile { public AuthorProfile() { CreateMap<AuthorModel, AuthorDTO>().ForMember (destination => destination.Address, map => map.MapFrom(source => source.Address1)); } } Use NullSubstitute in AutoMapper Suppose the Address field in the AuthorModel is null and you would like to have something like “No data” in lieu of a null value. Here’s where NullSubstitution comes into action. The following code snippet illustrates how it can be used to replace null values with “No data”. AutoMapper.Mapper.CreateMap<AuthorModel, AuthorDTO>() .ForMember(destination => destination.Address, opt => opt.NullSubstitute("No data")); Use before and after mapping in AutoMapper Consider the following two classes. public class OrderModel { public int Id { get; set; } public string ItemCode { get; set; } public int NumberOfItems { get; set; } } public class OrderDTO { public int Id { get; set; } public string ItemCode { get; set; } public int NumberOfItems { get; set; } } You can take advantage of the BeforeMap() method to perform some calculation or initialize a data member in the source or destination instance. The following code snippet illustrates how this can be achieved. Mapper.Initialize(cfg => { cfg.CreateMap() .BeforeMap((src, dest) => src.NumberOfItems = 0) }); The AfterMap() method can be used to execute operations on the destination object after a mapping has been done. Here’s how you can use the AfterMap() method on the destination instance. public OrderDTO MapAuthor(IMapper mapper, OrderDTO orderDTO) { return mapper.Map<OrderModel, OrderDTO>(orderDTO, opt => { opt.AfterMap((src, dest) => { dest.NumberOfItems = _orderService.GetTotalItems(src); }); }); } Use nested mapping in AutoMapper AutoMapper can be used to map nested objects as well. Consider the following domain classes. public class Order { public string OrderNumber { get; set; } public IEnumerable<OrderItem> OrderItems { get; set; } } public class OrderItem { public string ItemName { get; set; } public decimal ItemPrice { get; set; } public int ItemQuantity { get; set; } } Consider the following classes that represent data transfer objects. public class OrderDto { public string OrderNumber { get; set; } public IEnumerable<OrderItemDto> OrderItems { get; set; } } public class OrderItemDto { public string ItemName { get; set; } public decimal ItemPrice { get; set; } public int ItemQuantity { get; set; } } You can use the following code to establish a mapping. var orders = _repository.GetOrders(); Mapper.CreateMap<Order, OrderDto>(); Mapper.CreateMap<OrderItem, OrderItemDto>(); var model = Mapper.Map<IEnumerable<Order>, IEnumerable<OrderDto>>(orders); AutoMapper enables you to map objects with minimal configuration. You can even map objects having different data structures by using a custom resolver. The custom resolver can generate an exchange object that has the same structure as the destination object so that the AutoMapper runtime can map the types at runtime. Related content feature What is Rust? Safe, fast, and easy software development Unlike most programming languages, Rust doesn't make you choose between speed, safety, and ease of use. Find out how Rust delivers better code with fewer compromises, and a few downsides to consider before learning Rust. By Serdar Yegulalp Nov 20, 2024 11 mins Rust Programming Languages Software Development how-to Kotlin for Java developers: Classes and coroutines Kotlin was designed to bring more flexibility and flow to programming in the JVM. Here's an in-depth look at how Kotlin makes working with classes and objects easier and introduces coroutines to modernize concurrency. By Matthew Tyson Nov 20, 2024 9 mins Java Kotlin Programming Languages analysis Azure AI Foundry tools for changes in AI applications Microsoft’s launch of Azure AI Foundry at Ignite 2024 signals a welcome shift from chatbots to agents and to using AI for business process automation. By Simon Bisson Nov 20, 2024 7 mins Microsoft Azure Generative AI Development Tools news Microsoft unveils imaging APIs for Windows Copilot Runtime Generative AI-backed APIs will allow developers to build image super resolution, image segmentation, object erase, and OCR capabilities into Windows applications. By Paul Krill Nov 19, 2024 2 mins Generative AI APIs Development Libraries and Frameworks Resources Videos