Fat Controller CQRS Diet: Notifications

CQRS NotificationsThis 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:

  1. Overview of Series
  2. Simple Query
  3. Simple Command
  4. Command Pipeline

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 correct IPostRequestHandler<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 interfaces INotification, 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 new AlbumAddedToCart notification to MediatR.  We can do so in our AddToCartHandler .

Comments

All the source code for this series is available on GitHub.GitHub

Which do you prefer, Pipeline or notifications? Let me know in the comments or on Twitter.


Fat Controller CQRS Diet: Command Pipeline

Command PipelineThis post is in my Fat Controller CQRS Diet series demonstrating 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.   All the source code is available on GitHub.

If you’re new to this series, here are earlier posts in this series:

  1. Overview of Series
  2. Simple Query
  3. Simple Command

Pipelines

In both the new  Query and Commands handlers wrote in prior posts, there was one thing standing out that really didn’t belong.

Logging

For reference, here was our AddToCartHandler that did some logging at the end of the method.

This really isn’t a concern of our AddToCartHandler.  One way we can separate logging out is by having our Command go through another handler after it’s been executed.  If we think about this a bit more broad, we can take it a step further and create a pipeline for our Command that can go through various handlers prior and after the main AddToCartHandler.

Video

If you prefer, I have a video tutorial that follows this blog post.

Decorators

One way to accomplish this is to use Decorators.  A decorator is nothing more than wrapper around our main handler.

In our example, we are going to use StructureMap.  In your project.json, add the following dependencies.

Next in our Startup.cs we are going to configure StructureMap in the IServiceProvider ConfigureServices(IServiceCollection) method.

The gist is we are going to Decorate/Wrap any ICancellableAsyncRequestHandler<TRequest,TResponse> in a Pipeline<TRequest,TResponse> (which we will create next).

Here is our implementation of the Pipeline<TRequest,TResponse>

It will take the primary request as the first argument in the ctor, and then a array of IPostRequestHandler<TRequest,TResponse>, which we will create next to define our logging handlers.

Log Handler

We now have everything in place to separate the logging from our AddToCartHandler.

All we need to know is create a class that will implement IPostRequestHandler<AddToCart,Unit> and it will be invoked after the AddToCartHandler.

Now we can jump back over to our AddToCartHandler and remove the ILogger and the logging code.

Validation, Authorization, Whatever

Hopefully now you can see that we could extend this to have pre-handlers that may do data validation, authorization or whatever other responsibilities that probably shouldn’t be in your main handler.

Comments

All the source code for this series is available on Github.GitHub

If have another way of creating a pipeline or separating concerns from your handlers, please leave comment or let me know on twitter.


Why use Nancy?

NancyFXOn one of my posts showing how you can use Nancy with ASP.NET Core, David Anderson posted the following comment

I came across some Nancy blogpost last week and got curious about it and so looked on internet for more information. I wanted to know why should someone use Nancy and why plain asp.net core is not sufficient. So far every place I look I see the same introduction, you know that one with ‘…super-duper-happy-path…’. But to be honest it’s still not clear ‘why’? What is it that someone can not do in ASP.NET Core which is ‘super-duper’ in Nancy? What is hard or missing in ASP.NET Core which is easy or available in Nancy? The need of such a framework on top of ASP.NET Core is very vage to me.

I realized that I never really blogged about why I started using Nancy.  I hinted at it slightly in my post about ASP.NET Core MVC Attribute Routing, but not in much detail.

MVC & Web API Routing

Like most, I primarily used ASP.NET MVC and Web API.  When I got into creating more Web API’s, the first thing that started causing me trouble was routing.

The convention based routing employed is to define your routes in the RouteCollection.  This is the familiar default route that you might have used before.

The primary issue I had with defining routes and route templates up front, was I to defined them closer to the code that was actually executing at a given endpoint.

Route Attributes do ultimately solve this problem and from what I’ve read recently, this seems to be the common way most now define routes.  However, I’m simply not a fan of attributes in this situation.  I won’t get into the reasons why, as I don’t think starting an attribute war serves much purpose for this post.

Nancy Routes

When I first seen how you defined routes in Nancy, I realized it was exactly what I was looking for.

Routes are defined in the constructor of a module. In order to define a route in Nancy, you need to specify a Method + Pattern + Action + (optional) Condition.

They’re just endpoints…

When you look at a Nancy module, you could compare it to a MVC or Web API Controller, but it’s really nothing more than a place you can define HTTP Endpoints.

This means you can use Modules as Controllers and develop using your familiar MVC pattern, or you could use them as Web API’s.  You can have your endpoint do whatever you need and return whatever you want.

Simple

Nancy by default is really simple to use.  You need zero configuration to get started.  Zero.

Add a Nancy Module and you are off to the races.

I’ve made a couple different posts on how you can use Nancy along side Web API in ASP.NET 4, and how you can use it with ASP.NET Core.

ASP.NET Core

Back to the comment and the last sentence:

The need of such a framework on top of ASP.NET Core is very vage to me

Nancy doesn’t replaces ASP.NET Core, but it could replace your need for ASP.NET Core MVC.

With the application pipeline (middleware) in ASP.NET Core, this allows you to leverage many different components that serve different purposes all within your web application.

For example you could use Nancy, ASP.NET Core MVC, Static File Server and Authentication.

More Reasons

There are many more reasons and many considerations. I highly recommend reading a post by Jonathan Channon that covers different aspects.  The post that’s a tad old, but still very relevant.

I really enjoy the conversation I get in some of the comments.  Please leave a comment here or on twitter.