MediatR logo borrowed from https://bit.ly/2N4Jz6S
When building robust APIs it it really important with validation and descriptive error messages and status codes.
In this post I am going to show you how you can get rid of duplicated code in your Request Handlers by adding MediatR behaviors to take care of validation for resource existence.
MediatR is an in-process messaging library in .NET that supports requests/responses, commands, queries, events etc. Go check it out if you haven’t.
In MediatR there is something called behaviors which allow you to build your own pipeline for requests. I use them for cross cutting concerns such as logging and validation of requests parameters.
Recently when some endpoints were developed for a microservice I struggled with duplicated code in my Request Handlers that was necessary to have in place.
To give you an example lets start with a couple of API endpoints, and also the implementation of the Request Handlers with the duplicated code.
The endpoints in this example are:
PUT /groups/{id}
POST /groups/{id}/users
The controller:
Both endpoints need to verify that the id-parameter actually matches a given group to be able to update a group / add user to a group (in my example I’m using EF Core as persistence, but you can safely ignore that).
As you can see there is an if-check for group existence in both the handlers.
How should we get rid of this duplication? Wouldn’t it be good to use some sort of “validation” here as a pre-step, so that the Request Handlers could look like this?
Thank behaviors for that! Let’s introduce an interface that both the requests: UpdateGroupRequest
and AddUserToGroupRequest
implement.
Then create a behavior implementation class with generic constraint to the interface defined above so that the behavior only applies to requests implementing the IGroupRequest
interface.
And a registration example using Autofac:
Now we can rewrite our Request Handlers without the if statements, but still get the benefit of validation!
Lets imagine we now add a couple of more endpoints:
GET /groups/{id}
POST /groups/{id}/permissions
Add the IGroupRequest
interface to your requests and you will get this feature out of the box. Pretty simple! I find this kind of approach really useful. What do you think?
We have to keep in mind that there are both some cons and pros to this approach. What I’ve found out is:
If you liked this post. You know what to do! 👏