Introduction to MediatR
MediatR is a CQRS style library developed by Jimmy Bogard and can be found at http://github.com/jbogard/mediatr.
Original ASP.NET architecture was focussed around a N-Tier Architecture where each tier dealt with each technical concern.
Service Layer, UI Layer, Business Layer and Database Layer.
It is possible to add more and more layers.
MediatR tries to enable a design based on behaviours or activities.
MediatR relies on the mediator pattern and aspects of the C# generics feature to connect MediatR Requests and Request Handlers.
A problem with the wiring?
The standard way to implement MediatR and the ASP.NET framework is to pull in the MediatR interface into the ASP.NET controllers.
Then fire off the send method after creating a request in the action method.
This is rather annoying.
An extra step in all the wiring up that needs to be done in the first place. ASP.NET controllers also follow a certain design paradigm including heavy usage of attributes and a lot of reflection under the hood.
It isn’t always clear what goes on under the hood, but isn’t that the point in frameworks?
The key point here is that this is a framework on top of another (in a way).
ASP.NET has middleware, which is the first gateway for a request.
ASP.NET MVC gets added to the middleware. So, we start off with one paradigm which is middleware, a standard approach to request/response. MVC comes along and does….. something different.
And the solution to the problem is ...
We’ve created a small library that cuts out the MVC proverbial middle man.
It allows for attaching a MediatR Request directly to middleware via an app extension method.
The extension method is simply a get, put, patch, post, delete that takes a generic argument of the MediatR Request, much like the send method.
This solution aims to combine two design considerations.
- The natural way to build up middleware, heavily utilising extension methods.
- Secondly, making it similar to using the MediatR send method.
The fact that both of these considerations can be met makes using both MediatR and ASP.NET feels natural and ultimately straightforward.
Now when you use MediatR you can focus more on the behaviours and activities rather than creating unnecessary layers.
A few considerations
ASP.NET Controllers are not the greatest design.
First things first. Does create have anything to do with delete?
For example, does registering a user (creating) have anything to do with removing a user (deleting)?
You could say yes because of the “user”... but to me that is just part of the “domain”.
So, what really is holding these two things together - a C# class.
More to that point, when you bring in dependencies into the controller, each method will “ask” for all of them.
Creating entities may involve some kind of messaging service.
Deleting may involve some further services checking for any relationships that need to be removed.
They don’t require the same dependencies but ASP.NET Controllers will make sure they’re all ready for either.
MediatR can’t do this because the Request Handlers only require their dependencies and only one Handler will be created per MediatR Request, which is only created by the request into ASP.NET.
Not all content types are supported by the library yet.
ASP.NET MVC does a great job of handling all the different ways to send data to an API, and dealing with basic API “miss” calls (a.k.a. calling methods that don’t exist, not specifying application/json.. that kind of stuff).
However, sometimes you can be left fighting the framework with this kind of stuff, like uploading files and the like.
What using middleware does, is offer up an easy way to extend what the connecting library does, in a way that works for ASP.NET middleware, not a framework another layer abstracted.
Immutable by default? Bring it on.
MediatR requests are great when they’re made immutable.
Newtonsoft JSON - which is used to bind the string http request body to the MediatR body - automatically handles immutable classes (maybe by using reflection to access properties, or using reflection to work out constructor arguments - either way works).
Therefore, without having to worry about how you make your MediatR Requests, they can be immutable by default.