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. It demonstrates how to thin your controllers by implementing commands and queries using the MediatR library. I’m converting the MusicStore application that’s using ASP.NET Core MVC. All the source code is available on GitHub. If you’re new to this series, here are earlier posts to get up to speed:Logging
In the my previous Command Pipeline example, I leveraged StructureMap and the decorator pattern to setup a pipeline. My pipeline would invoke the actual command handler as well as any classes that implemented the correctIPostRequestHandler<TRequest, TResponse>.
This enabled us to create a AddToCartLogHandler
which did our logging that was originally in the ShoppingCartController.AddToCart
action method.
Notifications
Another way to implement this is with a Notification (event). MediatR has this concept built in with a couple interfacesINotification
, IAsyncNotification
The concept and how it works with MediatR very similar as a request (Command or Query) and it’s appropriate handler. The difference with a Notification is it can have many handlers.
- Request: only one handler
- Notification: zero to many handlers
Implementation
I’m going to jump back to our AddToCart command. Instead of it using an IPostRequestHandler<AddToCart, Unit> that I created for our pipeline, I’m going to instead create a notification and publish that notification from MediatR. First, we need to create a class to represent our notification. All the class will contain is a property to specify the AlbumId that was added to the shopping cart. Now we will create a Notification Handler that will accept this new notification object and do the logging. Finally, our last piece is to Publish a newAlbumAddedToCart
notification to MediatR. We can do so in our AddToCartHandler
.
Hi Derek,
great article.
I’ve followed pretty much the same path but I’ve chosen to publish events in my MVC/Api controllers when I get back the result from the executed command.
I don’t know if this is the best choise but it seems kind of not-right to publish event from the command handler.
Could you help me to understand why you followed this path ?
Thanks,
Alberto
To be honest, I hadn’t really thought about publishing from the controller action. Interesting, makes me think.
I can see how not taking a dependency on IMediator in your request handler would be nice, however I guess the question would be how important is it that an event/notification is published? If you require it to be published, then having it outside of your handler poses a problem if you ever invoke that request somewhere else.
That makes sense.
Thanks.
For simple apps, you can use a Controller as an Application Service (use case host) and publish events from it, but if you’re building apps with multiples UIs (and multiple frameworks), it’s easier to have the business use case into its own app service and let that service care about publishing.
Very clean solution. Keep them coming 🙂 Cheers
I’m curious about why you would prefer this path over the pipeline path?
Or is this just teaching ‘another way’ without any preferences?
On one side, you’ll have a little more control in streamlining the event for each case, but an generic `INotification` implementation in the pipeline would remove the need for an explicit `Publish` in your code.
This was more just to show another way as an example. But yes, very valid point is you could have the notification published from the Pipeline.
I like the combo, the pipeline (or one implemented directly in the handler) doing the “write” ops & the notifications for related but not critical path operations.
Nice write up. Thanks for sharing!
What do you think of similar post – this time I called it round shape architecture
http://blog.tech-fellow.net/2016/10/30/baking-round-shaped-software-mapping-to-the-code/
Lol at Unit. Personally I’m using a `NoResult` type. I’m trying not to leak F# into C# 🙂
Pingback: The week in .NET – On .NET on MyGet – FlexViewer – I Expect You To Die | .NET Blog
Pingback: Szumma #070 – 2016 50. hét | d/fuel