Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use DTO interfaces in a Web API? [closed]

I'm experimenting with a web api in .NET Core 2, where I try to seperate concerns cleanly like in the examples here: https://msdn.microsoft.com/en-us/magazine/mt703433.aspx

One thing I am wondering about is: When using repository interfaces to set/get data, should the data types also be interfaces?

Example (reduced to emphasize the question):

public class ProjectController : Controller
{
    IProjectRepository _repo;

    [HttpGet]
    public IProject GetProject([FromRoute] string key)
    {
        return _repo.GetProject(key);
    }
}


public interface IProjectRepository
{
    IProject GetProject(string key);
}


// Implementation based on Entity Framework
public class EFProjectRepository : IProjectRepository
{
    private SomeEfContext _context;

    public IProject GetProject(string key)
    {
        return _context.Projects.SingleOrDefault(p => p.Key == key);
    }
}


public interface IProject
{
    string Key { get; set; }
    string Name { get; set; }
}


// EF specific implementation
public class Project : IProject
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string Key { get; set; }
    public string Name { get; set; }
}

My reason for doing it is, that if I don't, then the EF-implementation specific field Id will "bleed through" into the controller, which I do not want. As I said, this example is very simple, there are reasons for this Id field to be present - it becomes more obvious, when the example is extended with associated DTO's like "Task" etc.

Is there a better way to do this?

like image 847
Carsten Gehling Avatar asked Jan 01 '18 19:01

Carsten Gehling


People also ask

Should DTO have interfaces?

DTOs may inherit properties from multiple interfaces and using interfaces may reduce casting data between components and modules, especially in the boundaries of a single solution. Also, rules are often applied on interfaces, so DTOs should use them.

When should you use DTO?

DTO is really powerful. One use is to compose data from multiple objects to be transported. The second use is to hide your data object details away from the rest of the application and this can give you the ability to change the data objects.

Is using DTO a good practice?

Transfering data using Dtos between "local" services is a good practice but have a huge overhead on your developer team. There is some facts: Clients should not see or interact with Entities ( Daos ). So you always need Dtos for transferig data to/from remote (out of the process).

Where should I put my DTOs?

DTOs are inside Domain Layer... I think it really depends on where you intend to use those DTOs. For example, if the DTOs will mainly used by the frontend that relies on some private APIs then I would put the DTOs into the UI layer as other parts of the system do not need to know about those DTOs.


1 Answers

I haven't seen a DTO Interface, you could use it though if you have different clients with common properties. The problem I see is that you are mixing up between Entities (your Business Objects) and DTOs (what you send/receive from clients).
Normally, the Controller, being a client, would not know of the Repository layer. This should be knowledge of the service layer.
If you will only have a single data access layer that uses Entity Framework and you aren't planning on leaving it aside, I would recommend not to have a Repository layer at all, since it already implements both Repository (DbContext) and Unit Of Work (DbSet).

A standard SOLID architecture would look something like this (each being a separate project):

  • Project.Core
    • Visible to everyone
    • Does not contain any reference
    • Contains your DTOs and helper classes
  • Project.DataAccess
    • Visible to Domain
    • Contains your EF stuff
  • Project.Domain
    • Visible to Web only for configuring DI
    • References Core
    • Receives and returns DTOs
    • It is where your business logic actually is
  • Project.Abstractions
    • Visible to Web and Domain
    • Contains the interfaces of your services, which are implemented in Domain
  • Project.Tests
    • References Domain and Core
    • Contains your tests
  • Project.Web
    • References Domain, Abstractions and Core
    • Contains your actual Web APIs
    • Uses Dependency Injection to call Domain's services.
    • Receives either primitives (string, int, etc) or DTOs, and returns DTOs

Notice that only the domain/business layer actually sees the Entities that represent your database.

like image 95
Camilo Terevinto Avatar answered Oct 01 '22 05:10

Camilo Terevinto