AutoMapper ReverseMap in C#

AutoMapper ReverseMap in C# with Examples

In this article, I am going to discuss the AutoMapper ReverseMap in C# with some examples. Please read our previous article before proceeding to this article where we discussed how to map Complex type to Primitive Type using AutoMapper in C# with examples. This is one of the most important concepts to understand in AutoMapper and at the end of this article, you will understand how automapper reverse mapping in c# works.

What is AutoMapper Reverse Mapping in C#?

The Automapper Reverse Mapping is nothing but the two-way mapping which is also called as bidirectional mapping.

As of now, the mapping we discussed are one directional means if we have two types let’s say Type A and Type B, then we Map Type A with Type B. But using Automapper Reverse mapping it is also possible to Map Type B with Type A.

Let us understand C# AutoMapper Reverse Mapping with an example.

We are going to use the following three classes for this demo.

Reverse Mapping Using AutoMapper in C#

To implement the Reverse Mapping using Automapper in C# we need to use the ReverseMap option as shown in the below image.

Reverse Mapping Using AutoMapper in C#

Below is the complete example.

The code self explained. So, please go through the comment lines.

using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Step1: Initialize the Mapper
            var mapper = InitializeAutomapper();

            //Step2: Create the Order Request
            var OrderRequest = CreateOrderRequest();

            //Step3: Map the OrderRequest object to Order DTO
            var orderDTOData = mapper.Map<Order, OrderDTO>(OrderRequest);

            //Step4: Print the OrderDTO Data
            Console.WriteLine("After Mapping - OrderDTO Data");
            Console.WriteLine("OrderId : " + orderDTOData.OrderId);
            Console.WriteLine("NumberOfItems : " + orderDTOData.NumberOfItems);
            Console.WriteLine("TotalAmount : " + orderDTOData.TotalAmount);
            Console.WriteLine("CustomerId : " + orderDTOData.CustomerId);
            Console.WriteLine("Name : " + orderDTOData.Name);
            Console.WriteLine("Postcode : " + orderDTOData.Postcode);
            Console.WriteLine("MobileNo : " + orderDTOData.MobileNo);
            Console.WriteLine();

            //Step5: modify the OrderDTO data
            orderDTOData.OrderId = 10;
            orderDTOData.NumberOfItems = 20;
            orderDTOData.TotalAmount = 2000;
            orderDTOData.CustomerId = 5;
            orderDTOData.Name = "Smith";
            orderDTOData.Postcode = "12345";

            //Step6: Reverse Map
            mapper.Map(orderDTOData, OrderRequest);

            //Step7: Print the Order Data
            Console.WriteLine("After Reverse Mapping - Order Data");
            Console.WriteLine("OrderNo : " + OrderRequest.OrderNo);
            Console.WriteLine("NumberOfItems : " + OrderRequest.NumberOfItems);
            Console.WriteLine("TotalAmount : " + OrderRequest.TotalAmount);
            Console.WriteLine("CustomerId : " + OrderRequest.Customer.CustomerID);
            Console.WriteLine("FullName : " + OrderRequest.Customer.FullName);
            Console.WriteLine("Postcode : " + OrderRequest.Customer.Postcode);
            Console.WriteLine("ContactNo : " + OrderRequest.Customer.ContactNo);
            Console.ReadLine();
        }

        private static Order CreateOrderRequest()
        {
            return new Order
            {
                OrderNo = 101,
                NumberOfItems = 3,
                TotalAmount = 1000,
                Customer = new Customer()
                {
                    CustomerID = 777,
                    FullName = "James Smith",
                    Postcode = "755019",
                    ContactNo = "1234567890"
                },
            };
        }

        static Mapper InitializeAutomapper()
        {

            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Order, OrderDTO>()
                    //OrderId is different so map them using For Member
                    .ForMember(dest => dest.OrderId, act => act.MapFrom(src => src.OrderNo))

                    //Customer is a Complex type, so Map Customer to Simple type using For Member
                    .ForMember(dest => dest.Name, act => act.MapFrom(src => src.Customer.FullName))
                    .ForMember(dest => dest.Postcode, act => act.MapFrom(src => src.Customer.Postcode))
                    .ForMember(dest => dest.MobileNo, act => act.MapFrom(src => src.Customer.ContactNo))
                    .ForMember(dest => dest.CustomerId, act => act.MapFrom(src => src.Customer.CustomerID))
                    .ReverseMap();
            });
            
            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Order
    {
        public int OrderNo { get; set; }
        public int NumberOfItems { get; set; }
        public int TotalAmount { get; set; }
        public Customer Customer { get; set; }
    }
    public class Customer
    {
        public int CustomerID { get; set; }
        public string FullName { get; set; }
        public string Postcode { get; set; }
        public string ContactNo { get; set; }
    }
    public class OrderDTO
    {
        public int OrderId { get; set; }
        public int NumberOfItems { get; set; }
        public int TotalAmount { get; set; }
        public int CustomerId { get; set; }
        public string Name { get; set; }
        public string Postcode { get; set; }
        public string MobileNo { get; set; }
    }
}

When you run the application, it displays the data as expected as shown in the below image.

Reverse Mapping Using AutoMapper in C#

Modifying Models:

Let us modify the models as shown below. As you can see in the below image, now the complex type property is present in the OrderDTO class and primitive types are present in the Order class. 

Reverse Mapping Using AutoMapper in C#

Let’s implement the AutoMapper ReverseMap() function and see whether we get the results as expected or not. Modify the Mapper initialization to implement mapping and reverse mapping for the above types as shown in the below image.

AutoMapper Reverse Mapping in C#

Below is the code for the complete example
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Step1: Initialize the Mapper
            var mapper = InitializeAutomapper();

            //Step2: Create the Order Request
            var OrderRequest = CreateOrderRequest();

            //Step3: Map the OrderRequest object to Order DTO
            var orderDTOData = mapper.Map<Order, OrderDTO>(OrderRequest);

            //Step4: Print the OrderDTO Data
            Console.WriteLine("After Mapping - OrderDTO Data");
            Console.WriteLine("OrderId : " + orderDTOData.OrderId);
            Console.WriteLine("NumberOfItems : " + orderDTOData.NumberOfItems);
            Console.WriteLine("TotalAmount : " + orderDTOData.TotalAmount);
            Console.WriteLine("CustomerId : " + orderDTOData.customer.CustomerID);
            Console.WriteLine("FullName : " + orderDTOData.customer.FullName);
            Console.WriteLine("Postcode : " + orderDTOData.customer.Postcode);
            Console.WriteLine("ContactNo : " + orderDTOData.customer.ContactNo);
            Console.WriteLine();

            //Step5: modify the OrderDTO data
            orderDTOData.OrderId = 10;
            orderDTOData.NumberOfItems = 20;
            orderDTOData.TotalAmount = 2000;
            orderDTOData.customer.CustomerID = 5;
            orderDTOData.customer.FullName = "James Smith";
            orderDTOData.customer.Postcode = "12345";

            //Step6: Reverse Map
            mapper.Map(orderDTOData, OrderRequest);

            //Step7: Print the Order Data
            Console.WriteLine("After Reverse Mapping - Order Data");
            Console.WriteLine("OrderNo : " + OrderRequest.OrderNo);
            Console.WriteLine("NumberOfItems : " + OrderRequest.NumberOfItems);
            Console.WriteLine("TotalAmount : " + OrderRequest.TotalAmount);
            Console.WriteLine("CustomerId : " + OrderRequest.CustomerId);
            Console.WriteLine("Name : " + OrderRequest.Name);
            Console.WriteLine("Postcode : " + OrderRequest.Postcode);
            Console.WriteLine("MobileNo : " + OrderRequest.MobileNo);
            Console.ReadLine();
        }

        private static Order CreateOrderRequest()
        {
            return new Order
            {
                OrderNo = 101,
                NumberOfItems = 3,
                TotalAmount = 1000,
                CustomerId = 777,
                Name = "James Smith",
                Postcode = "755019",
                MobileNo = "1234567890"
            };
        }

        static Mapper InitializeAutomapper()
        {

            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Order, OrderDTO>()
                    .ForMember(dest => dest.OrderId, act => act.MapFrom(src => src.OrderNo))
                    .ForMember(dest => dest.customer, act => act.MapFrom(src => new Customer()
                    {
                        CustomerID = src.CustomerId,
                        FullName = src.Name,
                        Postcode = src.Postcode,
                        ContactNo = src.MobileNo
                    }))
                    .ReverseMap();
            });
            
            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Order
    {
        public int OrderNo { get; set; }
        public int NumberOfItems { get; set; }
        public int TotalAmount { get; set; }
        public int CustomerId { get; set; }
        public string Name { get; set; }
        public string Postcode { get; set; }
        public string MobileNo { get; set; }
    }
    public class Customer
    {
        public int CustomerID { get; set; }
        public string FullName { get; set; }
        public string Postcode { get; set; }
        public string ContactNo { get; set; }
    }
    public class OrderDTO
    {
        public int OrderId { get; set; }
        public int NumberOfItems { get; set; }
        public int TotalAmount { get; set; }
        public Customer customer { get; set; }
    }
}

Now run the application and see the output.

Reverse Mapping Using AutoMapper in C#

As you can see from the above output, the automapper reverse mapping work as expected for the primitive types but not working for the complex type.

So when both classes have members that are named equally then the AutoMapper ReverseMap() function works as expected. But if the classes contain members that are different and not mapped via the default (per naming) mapping then this does not work as expected.

How to make the two mapping works as expected?

If you want to make the two-way mapping work as expected then you need to do the Mapping via ForMember. So modify the Mapper initialization to tell the mapping for the complex type as shown in the below image.

AutoMapper Reverse Mapping for Complex Type in C#

Below is the complete code.
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Step1: Initialize the Mapper
            var mapper = InitializeAutomapper();

            //Step2: Create the Order Request
            var OrderRequest = CreateOrderRequest();

            //Step3: Map the OrderRequest object to Order DTO
            var orderDTOData = mapper.Map<Order, OrderDTO>(OrderRequest);

            //Step4: Print the OrderDTO Data
            Console.WriteLine("After Mapping - OrderDTO Data");
            Console.WriteLine("OrderId : " + orderDTOData.OrderId);
            Console.WriteLine("NumberOfItems : " + orderDTOData.NumberOfItems);
            Console.WriteLine("TotalAmount : " + orderDTOData.TotalAmount);
            Console.WriteLine("CustomerId : " + orderDTOData.customer.CustomerID);
            Console.WriteLine("FullName : " + orderDTOData.customer.FullName);
            Console.WriteLine("Postcode : " + orderDTOData.customer.Postcode);
            Console.WriteLine("ContactNo : " + orderDTOData.customer.ContactNo);
            Console.WriteLine();

            //Step5: modify the OrderDTO data
            orderDTOData.OrderId = 10;
            orderDTOData.NumberOfItems = 20;
            orderDTOData.TotalAmount = 2000;
            orderDTOData.customer.CustomerID = 5;
            orderDTOData.customer.FullName = "James Smith";
            orderDTOData.customer.Postcode = "12345";

            //Step6: Reverse Map
            mapper.Map(orderDTOData, OrderRequest);

            //Step7: Print the Order Data
            Console.WriteLine("After Reverse Mapping - Order Data");
            Console.WriteLine("OrderNo : " + OrderRequest.OrderNo);
            Console.WriteLine("NumberOfItems : " + OrderRequest.NumberOfItems);
            Console.WriteLine("TotalAmount : " + OrderRequest.TotalAmount);
            Console.WriteLine("CustomerId : " + OrderRequest.CustomerId);
            Console.WriteLine("Name : " + OrderRequest.Name);
            Console.WriteLine("Postcode : " + OrderRequest.Postcode);
            Console.WriteLine("MobileNo : " + OrderRequest.MobileNo);
            Console.ReadLine();
        }

        private static Order CreateOrderRequest()
        {
            return new Order
            {
                OrderNo = 101,
                NumberOfItems = 3,
                TotalAmount = 1000,
                CustomerId = 777,
                Name = "James Smith",
                Postcode = "755019",
                MobileNo = "1234567890"
            };
        }

        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Order, OrderDTO>()

                     .ForMember(dest => dest.OrderId, act => act.MapFrom(src => src.OrderNo))
                     .ForMember(dest => dest.customer, act => act.MapFrom(src => new Customer()
                     {
                         CustomerID = src.CustomerId,
                         FullName = src.Name,
                         Postcode = src.Postcode,
                         ContactNo = src.MobileNo
                     }))

                     .ReverseMap()

                     .ForMember(dest => dest.CustomerId, act => act.MapFrom(src => src.customer.CustomerID))
                     .ForMember(dest => dest.Name, act => act.MapFrom(src => src.customer.FullName))
                     .ForMember(dest => dest.MobileNo, act => act.MapFrom(src => src.customer.ContactNo))
                     .ForMember(dest => dest.Postcode, act => act.MapFrom(src => src.customer.Postcode));

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

    public class Order
    {
        public int OrderNo { get; set; }
        public int NumberOfItems { get; set; }
        public int TotalAmount { get; set; }
        public int CustomerId { get; set; }
        public string Name { get; set; }
        public string Postcode { get; set; }
        public string MobileNo { get; set; }
    }
    public class Customer
    {
        public int CustomerID { get; set; }
        public string FullName { get; set; }
        public string Postcode { get; set; }
        public string ContactNo { get; set; }
    }
    public class OrderDTO
    {
        public int OrderId { get; set; }
        public int NumberOfItems { get; set; }
        public int TotalAmount { get; set; }
        public Customer customer { get; set; }
    }
}

Now run the application and you will see the output as expected as shown in the below image.

Reverse Mapping Using AutoMapper in C#

In the next article, I am going to discuss Conditional Mapping using AutoMapper in C# with examples. Here, in this article, I try to explain AutoMapper Reverse Mapping in C# with examples. I hope this C# AutoMapper Reversemap article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

1 thought on “AutoMapper ReverseMap in C#”

Leave a Reply

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