AutoMapper in Web API with .NET 6
This article will explain about AutoMapper and its usage. Additionally, this article will present a step-by-step example of how to implement AutoMapper in a Web API project with .NET 6.
AutoMapper is one of the best libraries for developers, its library is saving development time with non-important activities for more than 10 years.
What is AutoMapper?
AutoMapper is the most common library used to map one object to another. With AutoMapper you can transmit the data in your input object to an output object, reusing the same conversion logic in the whole project.
Nowadays, most Web API architecture projects have more than 2 layers. If you apply a loosely coupled design between those layers then you will need to replicate objects in each one of those layers, bringing an additional complexity to managing those objects and transmitting data from the first layer to the last layer.
AutoMapper's main features are the ones as follows:
- Profile Classes, organizing your mappings.
- Naming Conventions, configuring the source and destination naming conventions.
- Reverse Mapping, mapping two objects both ways with fewer lines.
- Nested Mapping, mapping child objects.
- General Configuration, setting your preferences once in project startup.
Benefits of using AutoMapper
The biggest benefit of using AutoMapper in your project is a cleaner code, requiring fewer lines to transmit data between different objects. This cleaner code will also reflect in a shorter development time, requiring less time and code to map objects.
It also offers greater maintainability by centralizing the same mapping between the two different objects in a unique place. Imagine if you need to update the mapping between two objects, you would need to go through all the places where this map is applied, apply its update and test each case. With AutoMapper you only need to update a single place and can write unit tests to validate this mapping.
AutoMapper in Web API Implementation Step by Step
Create the Web API using .NET 6
And install the following nugets:
- AutoMapper.Extensions.Microsoft.DependencyInjection
- AutoMapper
Create the classes to be mapped in and out
In this sample, we have 2 classes to be mapped in and out.
CategoryDto
public class CategoryDto {
public CategoryDto() {
Products = new HashSet < ProductDto > ();
}
public string Name {
get;
set;
} = null!;
public string ? Description {
get;
set;
}
public virtual ICollection < ProductDto > Products {
get;
set;
}
}
Category
public class Category {
public Category() {
Products = new HashSet < Product > ();
}
public int CategoryId {
get;
set;
}
public string CategoryName {
get;
set;
} = null!;
public string ? Description {
get;
set;
}
public virtual ICollection < Product > Products {
get;
set;
}
}
ProductDto
public class ProductDto {
public ProductDto() {}
public string Name {
get;
set;
}
public int ? SupplierId {
get;
set;
}
public int ? CategoryId {
get;
set;
}
public string ? QuantityPerUnit {
get;
set;
}
public decimal ? UnitPrice {
get;
set;
}
public short ? UnitsInStock {
get;
set;
}
public short ? UnitsOnOrder {
get;
set;
}
public short ? ReorderLevel {
get;
set;
}
public bool Discontinued {
get;
set;
}
public virtual CategoryDto ? Category {
get;
set;
}
}
Product
public class Product {
public Product() {}
public int ProductId {
get;
set;
}
public string ProductName {
get;
set;
} = null!;
public int ? SupplierId {
get;
set;
}
public int ? CategoryId {
get;
set;
}
public string ? QuantityPerUnit {
get;
set;
}
public decimal ? UnitPrice {
get;
set;
}
public short ? UnitsInStock {
get;
set;
}
public short ? UnitsOnOrder {
get;
set;
}
public short ? ReorderLevel {
get;
set;
}
public bool Discontinued {
get;
set;
}
public virtual Category ? Category {
get;
set;
}
}
Update the Program.cs
Include the following line to inject the AutoMapper into the .NET dependency injection.
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
Complete program.cs class,
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Create the AutoMapper Profile classes
The profile class is responsible to map the input class to the output class.
CategoryProfile
public class CategoryProfile: Profile {
public CategoryProfile() {
CreateMap < CategoryDto, Category > ().ForMember(dest => dest.CategoryName, opt => opt.MapFrom(src => src.Name)).ForMember(dest => dest.CategoryId, opt => opt.Ignore());
CreateMap < Category, CategoryDto > ().ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.CategoryName));
}
}
ProductProfile
public class ProductProfile: Profile {
public ProductProfile() {
CreateMap < ProductDto, Product > ().ForMember(dest => dest.ProductName, opt => opt.MapFrom(src => src.Name)).ForMember(dest => dest.ProductId, opt => opt.Ignore());
CreateMap < Product, ProductDto > ().ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.ProductName));
}
}
Using the AutoMapper
A Controller was created to map from one class to another, with one example of each one of the possible mappings with the classes created above.
[Route("api/[controller]")]
[ApiController]
public class ConversionController: ControllerBase {
private IMapper Mapper {
get;
}
public ConversionController(IMapper mapper) {
this.Mapper = mapper;
}
[HttpPost("FromCategoryDtoToCategoryEntity")]
public Category PostFromCategoryDtoToCategoryEntity([FromBody] CategoryDto categoryDto) {
return Mapper.Map < Category > (categoryDto);
}
[HttpPost("FromCategoryEntityToCategoryDto")]
public CategoryDto PostFromCategoryEntityToCategoryDto([FromBody] Category categoryEntity) {
return Mapper.Map < CategoryDto > (categoryEntity);
}
[HttpPost("FromProductDtoToProductEntity")]
public Product PostFromProductDtoToProductEntity([FromBody] ProductDto productDto) {
return Mapper.Map < Product > (productDto);
}
[HttpPost("FromProductEntityToProductDto")]
public ProductDto PostFromProductEntityToProductDto([FromBody] Product productEntity) {
return Mapper.Map < ProductDto > (productEntity);
}
}
Congratulations! You have successfully integrated AutoMapper in a Web API project with .NET 6.
External References