TimeCoder
@TimeCoder

Как правильно использовать DTO в реальных проектах asp.net core WebAPI?

Доброго времени,
с принципами SOLID в общем, и использовании DI-контейнеров, слоев, разных архитектур все понято. Вопрос более сложный, про то, как это работает в больших крутых проектах, с поправкой, что речь именно о WebAPI на базе asp.net core. Думаю, что многим будет интересно прочитать ответы, кто какие подходы использует.

У меня по совокупности практики и теории сложилась такая картина (Business, Data - это папки, остальное проекты, все это в одном солюшене):
Data
|___Project.Data.Contracts
|___Project.Data.Impl
Business
|___Project.Services.Contracts
|___Project.Services.Impl
WebApi
Смысл в том, что все сервисы и репозитории регистрируются в DI, и могут быть использованы в любом месте.
Общая логика такова:
1. В контроллер прилетает запрос, код метода почти из одной строки: идет вызов метода из нужного сервиса. Еще можем тут же проверять авторизацию.
2. В сервисе вся логика, основной код, и там же дергаются репозитории.

Вот теперь самое главное. На простом примере, пусть сущность User.
Есть UserController в WebApi, в слое сервисов, допустим, только логика, объекта User нет. Он есть в слое DAL, причем в Project.Data.Contracts находится IUser, а в Project.Data.Impl - просто User. Понятно, что вот этот User содержит "database-specific" обвески, например, атрибуты EntityFramework. Мы не можем этот объект выпускать за пределы слоя данных, репозиторий отдает, конечно, его под видом IUser. Но что мы используем на уровне WebApi? Нужна ли в данном случае своего рода ViewModel?

Другими словами: нужен ли еще один класс, реализующий IUser, используемый как DTO в работе самого WebAPI?

Понятно, что он может и не наследовать IUser (просто конвертировать AutoMapper'ом). Мне видится, что он нужен (его будет получать или возвращать контроллер), но вот код дублируется. Получается 3 почти идентичных куска кода: IUser, User (DB), UserViewModel (WebApi).

Есть немного другой путь: не использовать EntityFramework (вполне реальные кейсы), взять, например, Dapper. Там в классе User не будет атрибутов, он будет чистым DTO. И теоретически, мог бы использоваться в WebAPI, но тогда придется сделать прямую ссылку на Project.Data.Impl. Точнее говоря, эта ссылка и так есть (нам же надо в Startup.cs зарегистрировать все репозитории, а DI из коробки asp.net core не поддерживает модули и их сканирование, в отличие от Ninject), но архитектурно это не правильно. Если только не вынести такие объекты в еще один проект.

Спасибо, что дочитали)
  • Вопрос задан
  • 5195 просмотров
Решения вопроса 2
qonand
@qonand
Software Engineer
Другими словами: нужен ли еще один класс, реализующий IUser, используемый как DTO в работе самого WebAPI?

В Вашей ситуации слой сервисов должен возвращать в WebApi DTO, но реализовывать его как IUser не стоит. Разделение системы на слои подразумевает что каждый слой может знать только о нижележащем слое (точнее о его интерфейсах). Если DTO, возвращаемое в WebAPI, будет реализовывать IUser относящийся к DAL произойдет нарушение порядка слоев, что как бы ни разу не тру.
Получается 3 почти идентичных куска кода: IUser, User (DB), UserViewModel (WebApi).

Вы этого никак не избежите, если хотите делить приложение на слои... сейчас у Вас структуры данных - идентичны, но со временем в системе может что-то поменять и они таковыми перестануть быть

Есть немного другой путь: не использовать EntityFramework (вполне реальные кейсы), взять, например, Dapper. Там в классе User не будет атрибутов, он будет чистым DTO. И теоретически, мог бы использоваться в WebAPI, но тогда придется сделать прямую ссылку на Project.Data.Impl.

Если User останеться в DAL - тогда проблема не решиться, у Вас по прежнему будет нарушение порядка слоев ...
Ответ написан
AlexanderByndyu
@AlexanderByndyu
IT-архитектор, эксперт в Agile&Lean
TimeCoder я подробно рассматривал этот вопрос в статье blog.byndyu.ru/2012/05/viewmodel-domain-model.html

Если останутся вопросы, буду рад ответить.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Искра Екатеринбург
от 80 000 до 100 000 ₽
Art gorka Санкт-Петербург
от 60 000 ₽
от 40 000 до 60 000 ₽
19 апр. 2024, в 16:34
30000 руб./за проект
19 апр. 2024, в 16:22
30000 руб./за проект
19 апр. 2024, в 16:18
19000 руб./за проект