An ASP.NET MVC Web API implementation of Uncle Bob Martin's Clean Architecture example

Does the Controller have to know about the Presenter?

May 30 · 27 mins read

This post is just a personal inquiry into how to do a clean architecture implementation in ASP.NET MVC Web API without making the Controller know about the Presenter.

This might not give any value to you. :grin: If you want more valueable stuffs, read Steven van Deursen’s posts here and here instead.

In his talks on Clean Architecture, Uncle Bob gives this diagram as an example of how to implement it:

CleanArchitectureDesignByUncleBobMartin.png

In the diagram, the Controller does not point to the Presenter, which means that the Controller does not know about the Presenter. That means that there is no code like var presenter = new Presenter() inside the Controller. And there is no instance level field like private Presenter presenter, or instance level property like private Presenter presenter { get; set; } inside the Controller. (Maybe he knows intuitively that making the Controller know about the Presenter will make things harder to manage?? I don’t know. Maybe.)

More on this later…

Update, June 12, 2021: I just learned that Uncle Bob has an example of the Controller knowing about the Presenter here. This shows yet another example of the fact that the relationship between the Controller and the Presenter depends on the kind of application you are building.

So, like I said above, this post might not give any value to you. Don’t waste your time reading this, Read Steven van Deursen’s posts here and here instead.

But if you have time to waste, this post might give you an idea on what NOT to do in your ASP.NET MVC Web API application. :smile:

This post focuses only on the interaction between the Controller, the Interactor, and the Presenter of that diagram (of course, because ASP.NET MVC Web API only touches on those parts of the diagram). This post does not talk about the other parts of the diagram. If you want to understand everything in that diagram, I encourage you to watch his talks titled “Architecture: The Lost Years” or “Clean Architecture and Design”. And to read his artistically done article on it: “A Little Architecture”.

Descriptions

Let’s zoom in on that diagram (still using an image from Uncle Bob’s slides) and give a short description of some of the components that we will touch on in this blog post.

The dance between the Controller, the Interactor, and the Presenter

The Controller

— the one who receives InputData from the user or the client, converts that input into a RequestModel, then passes the RequestModel to the Interactor. (Note that the Controller in that diagram is not necessarily the same as the MVC-Controller in ASP.NET. But if we implement that diagram in ASP.NET, we will be using the MVC-Controller as our Controller.)

class Controller {
    void Process(InputData inputData) {
        var requestModel = new RequestModel { ... };
        ...
        this.interactor.Process(requestModel);
    }
}

The Interactor

— accepts the RequestModel given by the Controller, does the work described in the use case document, then creates a ResponseModel which it passes to the Presenter. (Maybe you have heard of things called Application Services, or Command Handlers, or Query Handlers, or Use Case Handlers. The Interactor has the same purpose as those things. And remember, if you watched Uncle Bob’s talks, that the ResponseModel here is NOT the same as the the HTTP Response that web developers are familiar with.)

class Interactor {
    void Process(RequestModel requestModel)  {
        try {
            ...
            var responseModel = new ResponseModel { ... };
            ...
            this.presenter.Present(responseModel);
        } catch (Error error) {
            this.presenter.PresentError(error.Message);
        }
    }
}

The Presenter

— accepts the ResponseModel given by the Controller, converts that into a ViewModel, then passes the ViewModel to the View which is the UI in our case.

class Presenter {
    void Present(ResponseModel responseModel) {
        var viewModel = new ViewModel { ... };
        ...
        this.view.Show(viewModel);
    }
    
    void PresentError(string errorMessage) {
        this.view.ShowError(errorMessage);
    }
}

The dance between the Interactor, and the Presenter

This is the diagram Uncle Bob uses to show the interaction between the Interactor and the Presenter.

The dance between the Interactor and the Presenter

The Boundary is an interface:

interface Boundary 
{
    void Present(ResponseModel responseModel);
}

We can see in that diagram that the Presenter points to the Boundary using an arrow with a hollow triangle-head.

Presenter pointing to Boundary

That means that the Presenter implements the Boundary, like this:

class Presenter : Boundary { ... }

(In C#, the Boundary is either an abtract class or an interface.)

Now, there are lots of objects called Boundary in Uncle Bob’s example, so we will name the Boundary that the Presenter implements as PresenterBoundary. Or maybe name it IPresenterBoundary (because it is customary in .NET to prefix interfaces with “I”). Or make it shorter, like IPresenter:

interface IPresenter 
{
    void Present(ResponseModel responseModel);
    void PresentError(string errorMessage);
}

class Presenter : IPresenter { ... }

Nice.

The Interactor points to the Boundary (or IPresenter) with a normal arrow head.

Interactor pointing to Boundary

That means that Interactor contains or uses an IPresenter. We will use the name UseCaseHandler for our Interactor:

class UseCaseHandler
{
    private IPresenter presenter;

    // constructor
    public UseCaseHandler(IPresenter presenter) 
    {
        this.presenter = presenter;
    }
}

Implementation in ASP.NET MVC Web API

When implementing Uncle Bob’s diagram in ASP.NET MVC Web API, the MVC-Controller (which I will call MVC_Controller here) will play the role of the Controller of Uncle Bob’s diagram, because in ASP.NET the MVC_Controller is the one who accepts the input (or InputData) from the user.

Now, the MVC-Controller, or MVC_Controller, is also the one who gives back the output (or ViewModel) to the user:

[ApiController]
[Route("api/clean-architecture-example")]
class MVC_Controller : ControllerBase
{
    [HttpPost]
    public IActionResult Process(InputData inputData)
    {
        ...
        var viewModel = new ViewModel();
        ...
        return Ok(viewModel);
    }
}

… that means that the MVC_Controller will also play the role of the Presenter.

We do that by making the MVC_Controller implement the IPresenter interface.

[ApiController]
[Route("api/clean-architecture-example")]
class MVC_Controller : ControllerBase, IPresenter
{
    private readonly UseCaseHandler interactor;

    private IActionResult Result;

    public MVC_Controller(UseCaseHandler interactor)
    {
        this.interactor = interactor;
    }

    #region "Controller"
    [HttpPost]
    public IActionResult Process(InputData inputData)
    {
        var requestModel = new RequestModel {...};
        this.interactor.Process(requestModel);
        return Result;
    }
    #endregion

    #region "Presenter"
    [NonAction]
    public void Present(ResponseModel responseModel)
    {
        var viewModel = new ViewModel();
        this.Result = Ok(viewModel);
    }

    [NonAction]
    public void PresentError(string errorMessage)
    {
        this.Result = Problem(errorMessage);
    }
    #endregion
}

Now, the Presenter needs a way to pass the ViewModel it produced to the MVC_Controller. That is what the private property IActionResult Result is for:

    ...
    private IActionResult Result;
    ...

the Presenter will put the ViewModel it produced into the Result property, then the Controller will access it after calling the Interactor’s Process method.

(That’s the most awkward code in this implementation — we have to remember to call the interactor.Process() before returning the Result. I might find a way someday to remove that awkward code. For now, writing a unit test to enforce that code sequence might help.)

Then in the main or entry point of the application, we construct our objects and register them to our IoC container:

services.AddScoped<UseCaseHandler>();
services.AddScoped<IPresenter, MVC_Controller>();
services.AddScoped<IRepository, Repository>();

Please note that the clean architecture implementation presented in this blog post — an ASP.NET implementation where the Controller does not know about the Presenter — might not be useful to softwares being built these days — the client-server kinds of applications.

Steven van Deursen’s implementation presented here and here seems best for those kinds of applications. If you follow that implementation, there is no need for a Presenter (or an IPresenter interface); the Controller will be the one who will create the ViewModels.

The implementation presented in this post is useful to software where there is a need for different kinds of Controllers and Presenters, which reuses the module where the Interactor resides.

For example, if you need to have Web API endpoints in the server, a console app in the server, and a rich-client app in the server, all of which uses the same Interactors — these three will have different Controllers and Presenters, but they reuse the Interactors.

WARNING: The code above will actually throw a circular dependency error like this:

System.AggregateException: 'Some services are not able to be constructed ...
A circular dependency was detected for the service of type ...

To solve that, we create a factory for our use case handlers:

public class UseCasesFactory
{
    private readonly IRepository repository;

    public UseCasesFactory(IRepository repository)
    {
        this.repository = repository;
    }

    private UseCaseHandler __useCaseHandler;
    public SendGreetingHandler CreateUseCaseHandler(IPresenter presenter)
    {
        if (__useCaseHandler == null)
            __useCaseHandler = new UseCaseHandler(presenter, repository);
        return __useCaseHandler;
    }
}

Then we remove the UseCaseHandler from our IoC container, and register our UseCasesFactory instead:

services.AddScoped<UseCasesFactory>();
services.AddScoped<IPresenter, MVC_Controller>();
services.AddScoped<IRepository, Repository>();

And then we use our UseCasesFactory in our Controller, passing the presenter instance during the creation of the UseCaseHandler, like this:

[ApiController]
[Route("api/clean-architecture-example")]
class MVC_Controller : ControllerBase, IPresenter
{
    private readonly UseCasesFactory factory;

    private IActionResult Result;

    public MVC_Controller(UseCasesFactory factory)
    {
        this.factory = factory;
    }

    [HttpPost]
    public IActionResult Process(InputData inputData)
    {
        var requestModel = new RequestModel {...};
        // pass in the presenter instance to the factory
        var interactor = this.factory.CreateUseCaseHandler(this);
        interactor.Process(requestModel);
        return Result;
    }
    
    ...
}

Have fun coding!

If you want code you can run, I’ve created a simple example here. Go to the csharp folder, open the solution file in Visual Studio 2019, then set the project named CleanAspNet.WebApi as the startup project. Then run the application.

I think this Clean Architecture idea is most valuable during the maintenance phase[1] of a software system, because it is during that phase when lots of changes in the business rules are going to happen, and changes in business rules can be implemented easily only if the software is structured properly.

I think that means that this Clean Architecture idea is very valuable only when the software is expected to become big, or when the software is expected to be used for many years, because in those cases the maintenance phase will be longer.

This Clean Architecture idea might not be very useful, and might be a waste of time[1] to implement, if your software will live only for a few months.

Actually, it will still be useful for you and for other devs if you use this Clean Architecture idea in smaller or short-lived softwares — you can use smaller softwares to practice doing clean architecture, because it’s better to practice doing clean architecture in the small. But, depending on your situation, you might have to ask permission from your employer, so that he will not be surprised if the initial phase of the project will take a long time to finish.


PS:

The ASP.NET MVC Web API code given in this post implements Uncle Bob’s diagram exactly the way it is drawn — where the Controller does not know about the Presenter. But this is not the only way to implement a clean architecture in an MVC-framework (so called). Other kinds of implementation are also given by others, for example here and here.

Some of these implementations make the Controller know about the Presenter, but with the tradeoff of making some duplicate logic in the Controller and the Interactor, especially on managing errors.

Some of these implementations are implemented the way Uncle Bob draws them in the diagram, but might not be compatible with the very interesting idea of using decorators to implement cross-cutting concerns, as presented by Steven van Deursen here and here, and by Mark Seemann here and here.


Footnotes:

[1] Of all the aspects of a software system, maintenance is the most costly. The never-ending parade of new features and the inevitable trail of defects and corrections consume vast amounts of human resources. … A carefully thought-through architecture vastly mitigates these costs. By separating the system into components, and isolating those components through stable interfaces, it is possible to illuminate the pathways for future features and greatly reduce the risk of inadvertent breakage. (Uncle Bob Martin, Clean Architecture: A Craftsman’s Guide to Software Structure and Design )

[1] … architectural boundaries exist everywhere. We, as architects, must be careful to recognize when they are needed. We also have to be aware that such boundaries, fully implemented, are expensive. On the other hand, we also have to recognize that when such boundaries are ignored, they are very expensive to add in later — even in the presence of comprehensive test-suites and refactoring discipline. (Uncle Bob Martin, Clean Architecture: A Craftsman’s Guide to Software Structure and Design )

Buy Me A Coffee