Automapper is one of the most widely adopted Object-To-Object Mappers that reduces a lot of the pain of developers. The purpose of Mapper is to reduce the amount of repeated code that a developer needs to write when assigning values from one Object To another. With much less configuration you can be up and running. Whenever we are creating applications, we have multiple layers. These multiple layers have different separation of concerns. To handle those separations of concern we have to create multiple entities that contain repeated multiple properties. In each layer we exclude those properties that should not be exposed to other layers due to security concerns or separation of concerns. Let's see what it means!!
Example
In Data Access Layer,
- public class Person {
- public string Id {
- get;
- set;
- }
- public string Name {
- get;
- set;
- }
- public DateTime DateOfBirth {
- get;
- set;
- }
- public string Username {
- get;
- set;
- }
- public string Password {
- get;
- set;
- }
- }
In Service Layer,
- public class PersonRequest {
- public string Username {
- get;
- set;
- }
- public string Password {
- get;
- set;
- }
- }
- public class PersonResponse {
- public string Name {
- get;
- set;
- }
- public int Age {
- get;
- set;
- }
- public string Username {
- get;
- set;
- }
- }
We have to perform mapping like this,
PersonRequest → Person
Person → PersonResponse
In Normal scenario we do like this,
For request handling,
- PersonRequest request = new PersonRequest();
- request.Username = “varun”;
- request.Password = ”Te$t”;
- Person person = new Person();
- person.Username = request.Username;
- person.Password = request.Password;
Now this Person type class is handled in DataAccess Layer inside a method to make a Login Call with a Parameter of Type Person. After the login call to the database we got the response. Now it's a lot of work to get only essential fields in the response,
-
- public Person Login(Person request){
-
- }
To get only essential fields in response, it';s a lot of work:
- Person person = new DataAccess().Login(personEntity);
- PersonResponse response = new PersonResponse();
- response.Name = person.Name;
-
-
Lots of extra code will be required, and imagine these were 50 fields. No, we don’t need that much manual work to waste our time. This is a small example with limited properties, in real life we can have more than 20 properties, 50 or more depending upon the complexity. To overcome such issues we have Object-Object Mappers.Then automapper is a timesaver. Now, let us see a practical automapper example along with configuration,
Pre-Requisites
To install package,
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection
Namespace to Include,
using Automapper;
Code
Creating Mapping Profiles - Profiles are the best way to organize mapping
- public class ReqResToEntityProfile: Profile {
- public ReqResToEntityProfile() {
- CreateMap < Person, PersonResponse > ();
- CreateMap < PersonRequest, Person > ();
- }
- }
Code Configuration - In this example we are using Dependency Injection feature of .NET Core.
-
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddAutoMapper(typeof(ReqResToEntityProfile));
-
Invoking in Application,
- namespace Automapper.App.Controllers
- {
- public class HomeController : Controller
- {
- private readonly ILogger<HomeController> _logger;
- private IMapper mapper;
- public HomeController(ILogger<HomeController> logger,IMapper mapper)
- {
- _logger = logger;
- this.mapper = mapper;
- }
-
- public IActionResult Index()
- {
- var peoplesData = InMemoryData.Data.GetPeople();
- var response = mapper.Map<List<PersonResponse>>(peoplesData);
- return Ok(response);
- }
-
Result
- [{"name":"Varun","age":0,"username":"varun"},{"name":"John","age":0,"username":"john2"},{"name":"Megan","age":0,"username":"megan3"}]
Now, in the phase of mapping we have lost the conversion of DateOfBirth To Age. Let us find a solution for that.
For this purpose we will do some changes. New changes will look like this,
- public ReqResToEntityProfile()
- {
- CreateMap<Person,PersonResponse>()
- .ForMember(d=>d.Age,o=>o.MapFrom(s => DateTime.Now.Subtract(s.DateOfBirth).Days/365 ));
- CreateMap<PersonRequest,Person>();
- }
Result
- [{"name":"Varun","age":40,"username":"varun"},{"name":"John","age":30,"username":"john2"},{"name":"Megan","age":25,"username":"megan3"}]
Similar to this, we will transform Request Object To Person Object,
- public IActionResult RequestSample() {
- var peoplesData = InMemoryData.Data.GetPersonRequest();
- var request = mapper.Map < Person > (peoplesData);
- return Ok(request);
- }
Result
- {"id":null,"name":null,"dateOfBirth":"0001-01-01T00:00:00","username":"varun","password":"te$t"}
That's it!!
Extra Notes
Creating Application using .NET Core CLI,
dotnet new sln
dotnet new mvc -o "Automapper.App" -f netcoreapp3.1
dotnet sln add Automapper.App/Automapper.App.csproj
cd Automapper.App
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection
Sample Data Class,
- namespace Automapper.App.InMemoryData {
- public class Data {
- public static List < Person > GetPeople() {
- List < Person > persons = new List < Person > {
- new Person {
- Id = "1", Name = "Varun", DateOfBirth = new DateTime(1980, 1, 1), Password = "te$t", Username = "varun"
- },
- new Person {
- Id = "2", Name = "John", DateOfBirth = new DateTime(1990, 1, 1), Password = "te$ta", Username = "john2"
- },
- new Person {
- Id = "3", Name = "Megan", DateOfBirth = new DateTime(1995, 1, 1), Password = "te$tx", Username = "megan3"
- }
- };
- return persons;
- }
- public static PersonRequest GetPersonRequest() {
- PersonRequest request = new PersonRequest {
- Username = "varun",
- Password = "te$t"
- };
- return request;
- }
- }
- }
That's It! Thank you for reading. Source Code is available as an attachment. You can comment for suggestions and improvements.