I'm designing a relatively simple web application using .net core. I've mostly done desktop development in my career so far, so I'm a bit new to the nuances between desktop and web development.

In this application there is a business logic layer and a presentation logic layer which takes the business logic and transforms the properties into marked up output server-side and then returns the data to the client through a web API.

Due to the controls I'm using and the structure of the application, it makes sense to have this "presentation logic" layer on the server side, since some aspects of the presentation are actual business logic requirements (most of the presentation is handled in views, partial views and view components).

Currently the way that I am handling this is by injecting the business logic classes into presentation logic classes, then having the api controller return an interface to the presentation logic class.

A simplified example of the approach:

public class BusinessLogic
{
  public string PropertyA { get; set; }

  public string PropertyB { get; set; }

  public void DoSomeLogic() { // some code here }
}

public class PresentationLogic : IPresented
{
  private BusinessLogic businessLogic;

  public PresentationLogic(BusinessLogic businessLogic)
  {
    this.businessLogic = businessLogic;
  }

  public string PresentationPropertyA
  {
    get
    {
      return "<span class='businesslogicspecificclass'>" + this.businessLogic.PropertyA + "</span>";
    }
  }
}

public interface IPresented
{
  string PresentationPropertyA { get; }
}

[Route("api/[controller]")]
public class MyController
{
  [HttpGet]
  public IPresented Get()
  {
    var businessLogic = new BusinessLogic();
    // manipulate businessLogic
    return new PresentationLogic(businessLogic);
  }
}

The API exposes interfaces which are implemented by the PresentationLogic classes. As I understand it, these interfaces are then serialised into JSON and returned to the page to use within its controls.

A different approach to solving the same problem would be to create a DTO, and have the PresentationLogic class take the business logic and spit out the DTO, adding the extra markup to the properties during the creation of the DTO. For example:

public class PresentationLogic
{
  public Dto GetDtoFromBusinessLogic(BusinessLogic businessLogic)
  {
    return new Dto { PresentationPropertyA = "<span class='businesslogicspecificclass'>" + this.businessLogic.PropertyA + "</span>" };
  }
}

public class Dto
{
  public PresentationPropertyA { get; set; }
}

[Route("api/[controller]")]
public class MyController
{
  [HttpGet]
  public Dto Get()
  {
    var businessLogic = new BusinessLogic();
    // manipulate businessLogic
    var presentationLogic = new PresentationLogic();
    return presentationLogic.GetDtoFromBusinessLogic(businessLogic);
  }
}

What I want to know is what the advantages or disadvantages to each approach is.

As I understand it, both controller methods will return effectively the same JSON to the calling page.

The first approach feels more natural to me for the following reasons:

  • I do not like DTOs unless they're absolutely necessary since I believe that they tend to encourage anaemic domain models
  • The presentation logic class becomes an adapter class that sits between the business logic and the view. It has a clearly defined responsibility.
  • I have not created any classes purely for the purpose of acting as a return type - it feels like less wasted code.
  • I could potentially add new properties to the PresentationLogic class and implement a new interface if version 2 called for changes.
  • Interfaces feel like the natural tool for abstraction for C# code.

I was discussing this with other developers and they were suggesting that returning a DTO was the more standard way of approaching this problem. I have come up with a couple of reasons why this might be a better approach:

  • DTOs are clearly marked as such and nobody is tempted to add breaking logic to them.
  • If it's the standard way then it will help new developers to get up to speed.
  • Adding a new version forces the use of a new DTO class, which means that there's less potential to introduce breaking changes (though this could also be done with the other approach if needed)

Note that this question is generally about layered web architecture than specifically about my needs on this project. If no presentation logic needed to be added server-side, this question could easily be about business logic and persistence logic classes.

So which is better - using DTOs in a web API or using interfaces on complex objects in a web API?

有帮助吗?

解决方案

Here ADM is the right approach.

  1. There is no point returning an object with methods from a controller method. The object is immediately serialised and sent over the wire. Nothing recieves the method.

  2. The contoller actions will have shared dependencies on various services which you will want to reuse for each request. Inject these into the contoller so you dont have to recreate them each request.

  3. The incoming parameter to the controller action is a pure data object which you deserialise. If you attach methods to it, its for semantic reasons only.

So essentially you have a stream of data objects coming in, a persistent service which acts on each, and returns another data object in response.

In this case your domain object, containing you business rules is the service, not the data.

Now, on your client side, you might well have (jeeze its hard when people dont use real examples) Object.BusinessLogic() with the client for your api injected into it and used to implement the method.

It makes sense to use classic OOP here because the Object object is persisted and passed around.

许可以下: CC-BY-SA归因
scroll top