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. 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:
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.)
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.
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”.
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 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);
}
}
— 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);
}
}
}
— 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);
}
}
This is the diagram Uncle Bob uses to show the interaction 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.
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.
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;
}
}
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.
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 ) ↩