Automapper
ReverseMap
ForMember
bidirectional mapping
object mapping

Automapper bidirectional mapping with ReverseMap and ForMember

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In AutoMapper, ReverseMap() creates a mapping in the opposite direction, while ForMember() customizes how individual members are mapped. They work well together, but the key is understanding that once your DTO shape stops matching the domain shape exactly, the reverse direction often needs its own explicit rules.

What ReverseMap() Really Does

A basic mapping defines one direction only:

csharp
CreateMap<User, UserDto>();

That lets AutoMapper map User into UserDto. If you add ReverseMap(), AutoMapper also creates UserDto -> User.

csharp
CreateMap<User, UserDto>()
    .ReverseMap();

This is ideal when property names and types line up cleanly in both directions. If both classes have Id, Email, and IsActive, AutoMapper can usually map them with no extra configuration.

Use ForMember() When Names or Shapes Differ

Real DTOs often rename or flatten fields. That is where ForMember() becomes necessary.

csharp
1public class User
2{
3    public int Id { get; set; }
4    public string FirstName { get; set; } = "";
5    public string LastName { get; set; } = "";
6    public string Email { get; set; } = "";
7}
8
9public class UserDto
10{
11    public int Id { get; set; }
12    public string FullName { get; set; } = "";
13    public string EmailAddress { get; set; } = "";
14}

Mapping from domain model to DTO:

csharp
1CreateMap<User, UserDto>()
2    .ForMember(
3        d => d.FullName,
4        opt => opt.MapFrom(s => s.FirstName + " " + s.LastName)
5    )
6    .ForMember(
7        d => d.EmailAddress,
8        opt => opt.MapFrom(s => s.Email)
9    )
10    .ReverseMap()
11    .ForMember(
12        d => d.Email,
13        opt => opt.MapFrom(s => s.EmailAddress)
14    );

The important part is that configuration written after ReverseMap() applies to the reverse direction.

Reverse Mapping Is Not Magic

ReverseMap() is convenient, but it cannot automatically reverse every transformation. If you merge two fields into one, the reverse direction must decide how to split them again.

csharp
1CreateMap<User, UserDto>()
2    .ForMember(
3        d => d.FullName,
4        opt => opt.MapFrom(s => s.FirstName + " " + s.LastName)
5    )
6    .ReverseMap()
7    .ForMember(
8        d => d.FirstName,
9        opt => opt.MapFrom(s => s.FullName.Split(' ')[0])
10    )
11    .ForMember(
12        d => d.LastName,
13        opt => opt.MapFrom(s => s.FullName.Contains(' ')
14            ? s.FullName.Substring(s.FullName.IndexOf(' ') + 1)
15            : "")
16    );

That is a simple example, but it shows the main rule: once the forward mapping transforms data, the reverse side usually needs explicit logic too.

Use ForPath() for Nested Reverse Destinations

If the reverse target is nested, ForMember() is not enough. Use ForPath() instead.

csharp
1public class Customer
2{
3    public string Name { get; set; } = "";
4    public Address Address { get; set; } = new Address();
5}
6
7public class Address
8{
9    public string City { get; set; } = "";
10}
11
12public class CustomerDto
13{
14    public string Name { get; set; } = "";
15    public string CityName { get; set; } = "";
16}
17
18CreateMap<Customer, CustomerDto>()
19    .ForMember(d => d.CityName, opt => opt.MapFrom(s => s.Address.City))
20    .ReverseMap()
21    .ForPath(d => d.Address.City, opt => opt.MapFrom(s => s.CityName));

This is the correct way to push a flattened DTO field back into a nested destination object.

Validate the Profile Early

AutoMapper configuration errors are much cheaper to catch at startup than at runtime.

csharp
1using AutoMapper;
2
3var config = new MapperConfiguration(cfg =>
4{
5    cfg.AddMaps(typeof(Program).Assembly);
6});
7
8config.AssertConfigurationIsValid();
9var mapper = config.CreateMapper();

That validation step catches missing mappings, bad member paths, and a lot of reverse-mapping mistakes before they hit production requests.

Know When Two Separate Maps Are Better

If the DTO is lossy or intentionally different from the domain model, two explicit maps are often clearer than forcing everything through ReverseMap().

That is especially true when:

  • the DTO combines multiple source fields into one display string
  • the reverse direction needs database lookups
  • some destination properties should never be filled from the DTO
  • the validation rules differ by direction

In those cases, two separate CreateMap() calls are often easier to reason about than a single bidirectional setup.

Common Pitfalls

The biggest mistake is assuming ReverseMap() can automatically undo every forward transformation. It cannot infer how to rebuild information that was flattened, merged, or reformatted.

Another common issue is forgetting that rules after ReverseMap() apply to the reverse mapping. If the config order is unclear, the profile becomes hard to read.

People also misuse ForMember() when the reverse destination is nested. In that case, ForPath() is the correct tool.

Finally, do not use bidirectional mapping just because it exists. If the shapes are not truly symmetrical, separate maps are usually cleaner.

Summary

  • 'ReverseMap() creates an opposite-direction mapping in AutoMapper.'
  • 'ForMember() customizes named or transformed member mappings.'
  • Reverse mappings need explicit logic when the forward direction flattens or reshapes data.
  • Use ForPath() when the reverse destination is nested.
  • If the two types are not symmetrical, separate maps are often clearer than forcing bidirectional mapping.

Course illustration
Course illustration

All Rights Reserved.