ASP.NET Core Web API

Data Transfer Objects (DTOs) & AutoMapper

2 Views Updated 5/6/2026

Data Transfer Objects (DTOs) & AutoMapper

Never expose your Database Entity classes directly to the internet. Doing so is a massive security risk (Mass Assignment vulnerabilities) and tightly couples your database schema to your API contract. We solve this by using Data Transfer Objects (DTOs) to act as a secure middleman.

1. Why use DTOs?

❌ The Danger of Returning Entities
public class User 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string PasswordHash { get; set; } // CRITICAL LEAK!
}

[HttpGet("{id}")]
public ActionResult<User> GetUser(int id) 
{
    // You just leaked the user's password hash to the frontend...
    return _db.Users.Find(id); 
}
✅ The DTO Solution
public class UserResponseDto 
{
    public int Id { get; set; }
    public string Name { get; set; }
    // No PasswordHash field here!
}

[HttpGet("{id}")]
public ActionResult<UserResponseDto> GetUser(int id) 
{
    var user = _db.Users.Find(id);
    return new UserResponseDto { Id = user.Id, Name = user.Name }; 
}

2. Introducing AutoMapper

Manually mapping properties from an Entity to a DTO (as shown above) becomes incredibly tedious when objects have 50 properties. AutoMapper is an industry-standard library that automates this property-to-property copying.

dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection

Step 1: Create a Mapping Profile

using AutoMapper;

public class UserMappingProfile : Profile
{
    public UserMappingProfile()
    {
        // Source -> Destination
        CreateMap<User, UserResponseDto>();
        
        // Destination -> Source (Useful for POST requests)
        CreateMap<UserCreateDto, User>();
    }
}

Step 2: Register in Program.cs

// This automatically finds all classes inheriting from "Profile" and registers them
builder.Services.AddAutoMapper(typeof(Program));

Step 3: Use IMapper in the Controller

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

    public UsersController(ApplicationDbContext db, IMapper mapper)
    {
        _db = db;
        _mapper = mapper;
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<UserResponseDto>>> GetUsers()
    {
        var users = await _db.Users.ToListAsync();
        
        // AutoMapper magically converts the List of Entities into a List of DTOs!
        var dtos = _mapper.Map<IEnumerable<UserResponseDto>>(users);
        
        return Ok(dtos);
    }
}

3. Interview Mastery

Q: "AutoMapper's `_mapper.Map` happens in Application Memory. If we have 10,000 users in the database but the frontend only needs 2 columns (Id and Name), does AutoMapper cause an inefficient SQL Query (SELECT *) before mapping?"

Architect Answer: "Yes, if used incorrectly. If you run `await _db.Users.ToListAsync()` first, EF Core downloads every column (including heavy Photo byte[] columns) into RAM resulting in a `SELECT *`, and only THEN does AutoMapper strip them away into the DTO. To fix this, AutoMapper provides the `.ProjectTo<TDto>()` extension method. Instead of pulling data into RAM, `ProjectTo` intercepts the LINQ query and rewrites the physical SQL generated by EF Core into a highly optimized `SELECT Id, Name FROM Users`, downloading only the exact bytes necessary across the network."

ASP.NET Core Web API
1. Fundamentals & HTTP
Introduction to ASP.NET Core Web API REST Principles and HTTP Methods Controllers & ControllerBase Routing (Attribute vs Conventional) Action Return Types (IActionResult)
2. Request Handling
Model Binding (FromQuery, FromBody, FromRoute) Dependency Injection (DI) Deep Dive App Settings & The Options Pattern
3. Data Access & Architecture
EF Core Setup in Web API DbContext & Migrations Repository & Unit of Work Pattern Asynchronous Programming (async/await)
4. Data Transfer & Validation
Data Transfer Objects (DTOs) & AutoMapper Model Validation (DataAnnotations) FluentValidation Integration
5. Advanced Concepts
Global Exception Handling Middleware Content Negotiation (JSON vs XML) Pagination & Filtering Advanced Searching & Sorting HATEOAS (Hypermedia) Implementation Output Caching & Response Caching
6. Security & Authorization
Cross-Origin Resource Sharing (CORS) JWT Authentication Setup Access Tokens & Refresh Tokens Workflow Role-Based & Policy-Based Authorization API Key Authentication Rate Limiting & Throttling
7. Documentation & Testing
Swagger & OpenAPI Configuration Customizing API Documentation Unit Testing Controllers (xUnit & Moq) Integration Testing (WebApplicationFactory)
8. Microservices & Deployment
Consuming External APIs (IHttpClientFactory) Health Checks & Diagnostics API Versioning Strategies Deploying APIs (Docker & Azure)