Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.
This post is in my Fat Controller CQRS Diet series demonstrate how to thin your controllers by implementing commands and queries using the MediatR library.
For demonstration, I’m converting the MusicStore application that’s using ASP.NET Core MVC.
If you’re new to this series, here are earlier posts in this series:
A command is request to change the state of our domain.
The first controller action we are going to rewrite is ShoppingCartController.AddToCart
Here is what the method originally looked like this.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
As with our simple query, there are a couple things going on here.
MVC is handling the albumId which is pass as an parameter to the method.
We do some data access to get the album out of our EF DbContext
Pass the album to our ShoppingCart
Logging
Return a redirect to the Index action
Extract to Command
What we want to extract are the aspects that MVC is handling. From the list above it’s the AlbumId being passed the URL/Route and then redirecting to the Index action.
Everything else is our feature, so let’s extract it into a command.
To do so, we need two pieces of information to add to our Request/Command. The CartId and the AlbumId.
So we will create our Request/Command to contain that data.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Now we can create our handler for this Request/Command. Basically we are going to extract the majority of the code that was inside our Controller Action and put it into our handler.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
You’ll notice we have our constructor take a couple dependencies on our DbContext and the ILogger.
Thin Controller
Now we can jump back to our controller and create our AddToCart Request/Command and send to the Mediator, which will invoke our Handler.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
We’ve removed coupling of the the MVC framework from our feature code. We can now create AddToCart Request/Command from other locations and send along to the mediator to have it invoked.
Next
That’s a very simple command endpoint that we moved our logic to a Command Handler using MediatR.
Next up we we will handle a more complex handler.
All the source code for this series is available on Github.
If anyone has any comments, suggestions or recommendations please leave comment or let me know on twitter.
Yes, and if you use MediatR, you can use the ICancellableAsyncRequestHandler and have your handler accept it. Thus, pass it thru to whatever else can use it like EF.
Neat, I didn’t know about the “CancellationToken requestAborted” MVC feature!
Yes, and if you use MediatR, you can use the ICancellableAsyncRequestHandler and have your handler accept it. Thus, pass it thru to whatever else can use it like EF.
Pingback: Fat Controller CQRS Diet: Trade-offs - CodeOpinion
Pingback: Fat Controller CQRS Diet - CodeOpinion