MediatR Behaviors

MediatR BehaviorsI was happy and surprised to see that MediatR v3.0 was released yesterday.  One of the new features, which I was really looking forward to are pipeline behaviors.

A pipeline behavior is an implementation of IPipelineBehavior<TRequest, TResponse>. It represents a similar pattern to filters in ASP.NET MVC/Web API or pipeline behaviors in NServiceBus.

Changes

There are a couple major breaking changes to v3.  All of them I’m fairly happy about actually.

Messages

There is no distinction between sync, async (cancellable) requests or notifications.

You simply implement either IRequest or INotification.

You must still create the appropriate handler via either IRequestHandler, IAsyncRequestHandlerICancellableAsyncRequestHandler.

Async

To send a request or publish a notification simply use Task Send(IRequest) or Task Publish(INotification)

No longer does it have the “Async” convention of appending to the method name.  I know this is often debated about this convention.  I don’t mind it at all since there are no sync methods.

Behaviors

The new addition is the interface IPipelineBehavior<TRequest, TResponse>

This allows you to create implementation(s) that will invoked in the order they are registered with your container (returned from the MultiInstanceFactory delegate).

The simplest implementation, that does nothing but call the next possible behavior.

You can see how you can use this to create Pre and Post behaviors to create a pipeline.

Pre & Post Processors

Thankfully, these have already been created and built-in to v3.

RequestPreProcessorBehavior<TRequest, TResponse> and RequestPostProcessorBehavior<TRequest, TResponse> to the rescue.

These can be used to implementing the appropriate interface of IRequestPreProcess<TRequest,TResponse> and IRequestPostProcessor<TRequest,TResponse>

Note: Be sure to register your  IRequestPreProcess<TRequest,TResponse> and IRequestPostProcessor<TRequest,TResponse> as well as RequestPreProcessorBehavior<TRequest, TResponse> and RequestPostProcessorBehavior<TRequest, TResponse>  with your container.

Test Drive

I figured I would use my ASP.NET Core MVC Music Store application as a test bed.

You can refer to my Fat Controller CQRS Diet: Command Pipeline post to see how created a pipeline in MediatR v2.  It involved creating wrapper/decorator with StructureMap.

This is incredibly straight forward and does all the heavy lifting that the pipeline decorator that I created previous.

For our MusicStore app, we can change our AddToCart for logging to be done like this.

The above code completely removed my need for my custom Pipeline decorator using StructureMap.  Win.

ASP.NET Extension

If you are using ASP.NET Core, check out the MediatR.Extensions.Microsoft.DependencyInjection v2.x package.  It has also been updated to support MediatR v3.

It adds several extension methods, one of which is IServiceCollection.AddMediatR(Assembly) to register all the Handlers and Pre/PostProcessor in a given assembly.

Comments

Are you using MediatR?  Do you plan on upgrading to v3?  I love hearing your comments, questions and recommendations!  Please post a comments or on Twitter.


Fat Controller CQRS Diet: Vertical Slices

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.  Specifically in this post, I’ll look at organizing your code by vertical slices.

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
  5. Notifications

Organize by Feature

Feature Slices or Vertical Slices are the terms I’ve heard the most for what I call Organize by Feature.

I’ve just always characterized as organizing all relevant code and files from a command or query into a specific folder or hopefully single file.

I generally stay away from creating layers so the term Vertical Slices does make a lot of sense.

Whatever our feature slice is, it surely makes sense to keep all that code together.

Single File

If you’ve seen the code related to my Command Pipeline or Notifications posts, then you should already be able to tell where I’m heading in terms of organization.

I generally like to keep the command/query and it’s associated handler all within the same file.  In the case of our logging handler, I was also keeping it in this file.

Pretty simple.  One file for everything related to a command or query.

Controllers & Views

Well almost.  What I hadn’t really moved were the controllers or views.  So let’s do that now.

Controllers are pretty easy since by default they can live anywhere within your project. ASP.NET MVC Core will just pick them up.

Let’s work on our Home Query.  We will simply create a HomeController within our Home.cs file that currently contains our query and our handler.

Because we are no longer using the default routing, I’ve added the HttpGet attribute to the method to keep the route intact to what it was prior.

View Locator

By default, ASP.NET Core MVC will look in the ~/Views/ folder with default conventions.  But we want to put our view right along side our Home.cs file in our Features folder.

So I’ve moved all of the view files into our Features folder.  Our solution now looks like this:

 

In order to tell ASP.NET where our views are now at, we can implement the IViewLocationExpander

Now in the  IServiceProvider ConfigureServices(IServiceCollection services) method from our Startup.cs, we can can configure to use our new locator.

That’s it!

We now have one file that contains our controller, query and handler.  And right along side it we have our associated view.

Comments

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

I love hearing your comments, questions and recommendations as it usually leads me down to other blog posts.  Please post a comments or on Twitter.


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.