T
T
TimeCoder2017-07-04 23:36:34
ASP.NET
TimeCoder, 2017-07-04 23:36:34

How to properly use DTO in real asp.net core WebAPI projects?

Good time,
with the principles of SOLID in general, and the use of DI containers, layers, different architectures, everything is understood. The question is more complicated, about how it works in large cool projects, with the amendment that we are talking about WebAPI based on asp.net core. I think that it will be interesting for many to read the answers, who uses what approaches.
Based on the combination of practice and theory, I have the following picture (Business, Data are folders, the rest are projects, all in one solution):
Data
|___Project.Data.Contracts
|___Project.Data.Impl
Business
|___Project.Services.Contracts
|___Project .Services.Impl
WebApi The point
is that all services and repositories are registered with DI and can be used anywhere.
The general logic is as follows:
1. A request arrives in the controller, the method code is almost from one line: the method is called from the desired service. We can also check the authorization right there.
2. The service has all the logic, the main code, and the repositories are also twitching there.
Now here's the most important thing. For a simple example, let the entity User.
There is a UserController in WebApi, in the services layer, for example, only logic, there is no User object. It is in the DAL layer, and in Project.Data.Contracts is IUser, and in Project.Data.Impl is just User. It is clear that this User contains "database-specific" trims, for example, EntityFramework attributes. We cannot release this object outside the data layer, the repository gives it, of course, under the guise of IUser. But what do we use at the WebApi level? Do I need some kind of ViewModel in this case?
In other words: do we need another class that implements IUser, used as a DTO in the operation of the WebAPI itself?
It is clear that it may not inherit IUser (just convert it with AutoMapper). It seems to me that it is needed (the controller will receive or return it), but the code is duplicated. It turns out 3 almost identical pieces of code: IUser, User (DB), UserViewModel (WebApi).
There is a slightly different way: do not use EntityFramework (quite real cases), take, for example, Dapper. There will be no attributes in the User class, it will be pure DTO. And theoretically, it could be used in WebAPI, but then you have to make a direct link to Project.Data.Impl. More precisely, this link is already there (we need to register all repositories in Startup.cs, and DI from the asp.net core box does not support modules and scanning them, unlike Ninject), but this is not architecturally correct. Unless you take out such objects in another project.
Thank you for reading)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Maxim Fedorov, 2017-07-05
@TimeCoder

In other words: do we need another class that implements IUser, used as a DTO in the operation of the WebAPI itself?

In your situation, the service layer should return a WebApi DTO, but you should not implement it as an IUser. The division of the system into layers implies that each layer can only know about the underlying layer (more precisely, about its interfaces). If the DTO returned in the WebAPI implements IUser related to the DAL, the layer order will be violated, which, no matter how I never do.
You can’t avoid this if you want to divide the application into layers ... now your data structures are identical, but over time something can change in the system and they will cease to be such
There is a slightly different way: do not use EntityFramework (quite real cases), take, for example, Dapper. There will be no attributes in the User class, it will be pure DTO. And theoretically, it could be used in WebAPI, but then you have to make a direct link to Project.Data.Impl.
If the User remains in the DAL - then the problem will not be solved, you will still have a violation of the order of the layers ...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question