DEV Community

Renuka Patil
Renuka Patil

Posted on

DTOs and AutoMapper in .NET Core

🧾 DTOs and AutoMapper in .NET Core β€” Explained in Detail


βœ… What is a DTO?

DTO stands for Data Transfer Object.

➀ Purpose:

  • A DTO is a simple object used to transfer data between layers (usually between backend and frontend).
  • It hides internal models (e.g., EF Core entities) from the API response to keep your architecture clean and secure.

βœ… Example: Why Use DTOs?

Let’s say you have an entity class:

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string PasswordHash { get; set; } // Shouldn't be exposed!
    public DateTime DateOfBirth { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

If you return this directly in your API, the PasswordHash would be exposed 😱.

βœ… Instead, use a DTO:

public class UserDto
{
    public string Username { get; set; }
    public int Age { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Now the API only returns what’s relevant and safe.


πŸ”„ What is AutoMapper?

AutoMapper is a library that automatically maps one object type to another, like mapping an Entity to a DTO.

Without AutoMapper:

var userDto = new UserDto
{
    Username = user.Username,
    Age = CalculateAge(user.DateOfBirth)
};
Enter fullscreen mode Exit fullscreen mode

With AutoMapper:

var userDto = _mapper.Map<UserDto>(user);
Enter fullscreen mode Exit fullscreen mode

πŸ› οΈ How to Use AutoMapper in .NET Core

1. πŸ“¦ Install Package:

dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection
Enter fullscreen mode Exit fullscreen mode

2. 🧭 Create a Mapping Profile

public class AutoMapperProfiles : Profile
{
    public AutoMapperProfiles()
    {
        CreateMap<User, UserDto>()
            .ForMember(dest => dest.Age,
                       opt => opt.MapFrom(src => CalculateAge(src.DateOfBirth)));
    }

    private int CalculateAge(DateTime dob)
    {
        var today = DateTime.Today;
        var age = today.Year - dob.Year;
        if (dob.Date > today.AddYears(-age)) age--;
        return age;
    }
}
Enter fullscreen mode Exit fullscreen mode

3. πŸ”§ Register AutoMapper in Program.cs or Startup.cs

builder.Services.AddAutoMapper(typeof(AutoMapperProfiles).Assembly);
Enter fullscreen mode Exit fullscreen mode

4. πŸ§ͺ Use AutoMapper in Controller or Service

private readonly IMapper _mapper;

public UsersController(IMapper mapper)
{
    _mapper = mapper;
}

[HttpGet("{id}")]
public async Task<ActionResult<UserDto>> GetUser(int id)
{
    var user = await _context.Users.FindAsync(id);
    return _mapper.Map<UserDto>(user);
}
Enter fullscreen mode Exit fullscreen mode

🧠 Benefits of Using DTOs + AutoMapper

Benefit Description
πŸ”’ Security Prevent exposing sensitive fields like passwords
🎯 Performance Transfer only what is needed
♻️ Decoupling Prevent tight coupling between API and DB models
βš™οΈ Reusability Use different DTOs for different views (e.g., UserListDto, UserDetailsDto)
⏱ Saves Time AutoMapper reduces boilerplate mapping code

βœ… Summary:

Concept Purpose
DTO Simple object for data transfer between layers, hides domain internals
AutoMapper Tool to automatically map between objects (e.g., Entity β†’ DTO)

Here’s a complete working example of using DTOs and AutoMapper in a minimal .NET Core Web API project.


βœ… Example: DTO + AutoMapper in .NET 6/7 API

πŸ”§ Step 1: Create a New Web API Project

dotnet new webapi -n UserApiDemo
cd UserApiDemo
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ Step 2: Install AutoMapper Package

dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection
Enter fullscreen mode Exit fullscreen mode

πŸ§‘β€πŸ’» Step 3: Create the Entity (User.cs)

// Models/User.cs
namespace UserApiDemo.Models;

public class User
{
    public int Id { get; set; }
    public string Username { get; set; } = string.Empty;
    public string PasswordHash { get; set; } = string.Empty;
    public DateTime DateOfBirth { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

🧾 Step 4: Create the DTO (UserDto.cs)

// Dtos/UserDto.cs
namespace UserApiDemo.Dtos;

public class UserDto
{
    public string Username { get; set; } = string.Empty;
    public int Age { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

πŸ” Step 5: Create the Mapping Profile

// Helpers/AutoMapperProfiles.cs
using AutoMapper;
using UserApiDemo.Models;
using UserApiDemo.Dtos;

namespace UserApiDemo.Helpers;

public class AutoMapperProfiles : Profile
{
    public AutoMapperProfiles()
    {
        CreateMap<User, UserDto>()
            .ForMember(dest => dest.Age,
                       opt => opt.MapFrom(src => CalculateAge(src.DateOfBirth)));
    }

    private int CalculateAge(DateTime dob)
    {
        var today = DateTime.Today;
        var age = today.Year - dob.Year;
        if (dob.Date > today.AddYears(-age)) age--;
        return age;
    }
}
Enter fullscreen mode Exit fullscreen mode

πŸ—οΈ Step 6: Register AutoMapper in Program.cs

// Program.cs
using UserApiDemo.Helpers;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddAutoMapper(typeof(AutoMapperProfiles).Assembly);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Enter fullscreen mode Exit fullscreen mode

🌐 Step 7: Create Controller

// Controllers/UsersController.cs
using Microsoft.AspNetCore.Mvc;
using UserApiDemo.Models;
using UserApiDemo.Dtos;
using AutoMapper;

namespace UserApiDemo.Controllers;

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly IMapper _mapper;

    public UsersController(IMapper mapper)
    {
        _mapper = mapper;
    }

    [HttpGet("{id}")]
    public ActionResult<UserDto> GetUser(int id)
    {
        // Dummy user data (replace with DB logic in real app)
        var user = new User
        {
            Id = id,
            Username = "john_doe",
            PasswordHash = "encrypted",
            DateOfBirth = new DateTime(1995, 5, 10)
        };

        var userDto = _mapper.Map<UserDto>(user);
        return Ok(userDto);
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… Output Example from GET /api/users/1

{
  "username": "john_doe",
  "age": 30
}
Enter fullscreen mode Exit fullscreen mode

πŸš€ Summary

This project:

  • Defines an entity (User)
  • Hides sensitive info using a DTO (UserDto)
  • Maps them using AutoMapper
  • Returns clean, safe API responses

Happy Coding!

Top comments (0)