In this article, we will explore key techniques to ignore property in AutoMapper.
We will use the Ignore() method, the Ignore attribute, and the DoNotValidate() method. We will also discuss when and how to use each of the methods mentioned.
Without further ado, let’s start!
When to Ignore a Property in AutoMapper
Ignoring properties during mapping becomes crucial in scenarios where certain data fields are either irrelevant or we should not include them in the mapping process.
For example, our application may have complex domain objects we do not want to make available externally. Likewise, we may not want to return database objects to the client. To address this, we typically use Data Transfer Objects (DTOs).
Let’s illustrate this with a simple code example:
public class User { public int Id { get; set; } public string Email { get; set; } public string Password { get; set; } public bool IsAdmin { get; set; } public DateTime CreatedAt { get; set; } }
Here, we have a User
class that corresponds to the database table. It contains properties considered as sensitive, such as Password
and IsAdmin
. Therefore, we don’t want to expose them.
Using the Ignore Method to Ignore a Property in AutoMapper
The Ignore()
method allows us to declare which properties should not be mapped, providing granular control over the mapping configuration.
Let’s demonstrate the usage of the Ignore()
method with a code example.
Firstly, we need to define a DTO object:
public class UserDto { public int Id { get; set; } public string Password { get; set; } public bool IsAdmin { get; set; } public DateTime CreatedAt { get; set; } }
As already mentioned, we do not want the values of properties such as Password
or IsAdmin
to be passed to this object. For this reason, when creating the map, we must define which fields we want to ignore during the mapping:
var configuration = new MapperConfiguration(cfg => cfg.CreateMap<User, UserDto>() .ForMember(dest => dest.Password, opt => opt.Ignore()) .ForMember(dest => dest.IsAdmin, opt => opt.Ignore()));
Now all we need to do is create the mapper itself and perform the mapping:
var mapper = configuration.CreateMapper(); var userDto = mapper.Map<UserDto>(user);
The newly created DTO has all the properties set as in the User
class, except Password
and IsAdmin
. Since AutoMapper didn’t map them, they have default values:
*** User *** Id: 1 Email: [email protected] Password: Password123! IsAdmin: True CreatedAt: 21.05.2024 21:01:13 *** UserDto *** Id: 1 Password: IsAdmin: False CreatedAt: 21.05.2024 21:01:13
It is also worth mentioning that for library versions older than 8.0 ignoring properties is necessary when the destination object does not contain properties from the source object. Forgetting this will lead to an exception. The newer versions of the library allow us to avoid certain properties in the destination DTO and will not throw an error.
Using Ignore Attribute to Ignore a Property in AutoMapper
As an alternative to the Fluent API, AutoMapper allows us to use attributes. To ignore a destination member we can simply add the Ignore
attribute in the object class:
[AutoMap(typeof(User))] public class UserDetailsDto { public int Id { get; set; } public string Email { get; set; } [Ignore] public string Password { get; set; } [Ignore] public bool IsAdmin { get; set; } public DateTime CreatedAt { get; set; } }
There are also a few additional differences from the definition using the Fluent API. First, we need to remember to mark the DTO with the AutoMap(typeof(User))
attribute. Thanks to this, we no longer need to create a configuration object.
Now we just need to create and use the mapper:
var configuration = new MapperConfiguration(cfg => cfg.AddMaps(typeof(Program).Assembly)); var mapper = configuration.CreateMapper(); var userDetailsDto = mapper.Map<UserDetailsDto>(user);
As a result, we will again obtain a DTO corresponding to the User
class, omitting the properties marked with the Ignore
attribute:
*** User *** Id: 1 Email: [email protected] Password: Password123! IsAdmin: True CreatedAt: 21.05.2024 21:01:13 *** UserDetailsDto *** Id: 1 Email: [email protected] Password: IsAdmin: False CreatedAt: 21.05.2024 21:01:13
How to Use DoNotValidate Method
With the introduction of newer versions of AutoMapper, the Ignore()
method was renamed to DoNotValidate()
for source members to avoid confusion. It’s worth noting that Ignore()
remains valid, but now specifically for destination members. Therefore, while Ignore()
persists for excluding destination properties, DoNotValidate()
replaces it for source members in versions equal to or newer than 8.0.
As already mentioned, newer versions of the library do not throw errors when the destination DTO does not contain certain properties. This means that we no longer need to mark these source properties as ignored to ensure correct mapping.
However, AutoMapper includes an AssertConfigurationIsValid()
method that allows us to check whether the mapping we have configured is correct. In this case, not including the property in the destination DTO still won’t cause an exception but can help us find properties that accidentally don’t have their equivalents in the mapped objects.
However, sometimes that’s exactly what we need. Therefore, to show the library that the properties were not omitted by mistake, we can use the DoNotValidate()
method.
We update our UserDto
class and remove the Email
property.
Now we can create the mapping configuration and check if it’s valid:
var configuration = new MapperConfiguration(cfg => cfg.CreateMap<User, UserDto>(MemberList.Source)); configuration.AssertConfigurationIsValid();
The invocation of the AssertConfigurationIsValid()
method will result in an exception. In this case, we can improve our configuration and use the DoNotValidate()
method for the source object:
var configuration = new MapperConfiguration(cfg => cfg.CreateMap<User, UserDto>(MemberList.Source) .ForSourceMember(source => source.Email, opt => opt.DoNotValidate())); configuration.AssertConfigurationIsValid();
Conclusion
Effectively managing property exclusions in AutoMapper is essential knowledge while working with the library. By utilizing Ignore() or IgnoreAttribute for destination members and DoNotValidate() for source members, developers can prevent unnecessary data transfer and improve mapping precision.