DTO, маппинг и контракты API
↑ 3.3 Web API: контроллеры, Minimal API, валидация · ← Предыдущая · → Следующая
Зачем это на собесе
Проверяют, отделяете ли вы модель хранения от внешнего контракта, и как относитесь к AutoMapper.
Объяснение
DTO (Data Transfer Object) — форма данных на границе API. Контракт отделяется от сущностей БД и доменных моделей, чтобы менять их независимо и не «светить» лишнего (пароль-хэши, внутренние ID).
public record OrderDto(Guid Id, string Customer, decimal Total, IReadOnlyList<OrderItemDto> Items);
public record CreateOrderRequest(string Customer, IReadOnlyList<OrderItemRequest> Items);| Способ маппинга | Плюсы | Минусы |
|---|---|---|
Ручной (ToDto()) | явный, быстрый, легко отлаживать | много кода |
| Mapperly / source generators | без рефлексии, проверка на этапе компиляции | генерируемый код |
| AutoMapper | меньше кода | рефлексия, скрытая логика, ошибки в рантайме, лицензия |
Проекция в запросе (Select) | грузит только нужные поля | привязка к EF |
var dtos = await db.Orders
.Where(o => o.CustomerId == id)
.Select(o => new OrderDto(o.Id, o.Customer.Name, o.Total, ...))
.ToListAsync(ct);Контракты API
- Разделяйте запросы и ответы; не переиспользуйте одну модель для create/update/response.
- Добавление полей — совместимо, удаление и смена типа — ломающее изменение.
- Публикуйте схему (OpenAPI) и версионируйте.
- Используйте
record,init, nullable-аннотации для ясности контракта.
Нюансы и подводные камни
- Возврат EF-сущностей ведёт к циклам сериализации, ленивым запросам и утечке данных.
- Mass assignment (over-posting): не биндите тело прямо в сущность.
- Не смешивайте бизнес-логику в мапперах.
- Даты передавайте в ISO 8601 UTC, деньги — как
decimal/строка, а неdouble.
Практика
- Замените возврат сущностей на DTO и проекции
Select. - Реализуйте маппинг через Mapperly.
- Проверьте over-posting: добавьте поле
IsAdminи попробуйте его отправить.
Вопросы с ответами
Зачем DTO, если есть сущности?
Чтобы отделить внешний контракт от модели хранения, скрыть лишнее и менять их независимо.
Что не так с AutoMapper?
Скрытая рефлексия и сложная отладка, ошибки видны только в рантайме, соблазн класть логику в профили; многие команды выбирают явный маппинг или Mapperly.
Что такое over-posting?
Атака/ошибка, когда клиент присылает лишние поля, которые биндятся в сущность; лечится отдельными request-DTO.