Command Pattern in Web API2 with MediatR and Ninject

I ran across MediatR the other day while looking into the command pattern. Ive been working a lot with micro-services. So I wanted to see how I could use the Command Pattern in Web API 2 with MediatR and Ninject.

Project Configuration

From the project wiki, it seems Jimmy Bogard prefers StructureMap as a DI container. Ive been mostly using Ninject and the documentation wasnt quite as clear.

Rather than showing the least amount of code, lets create a new project and send an example command.

Step 1 Start a New ASP.NET Web Application and make sure Web API is selected.

Step 2 Installing NuGet Packages

Install the following NuGet packages

  • Ninject.Web.WebApi.WebHost
  • MediatR
  • Swashbuckle

We dont need Swashbuckle, but it makes it a lot easier to test.

Using MediatR

Ill show a trivial example that negates the command passed in. Your real world usage will be more complex. But this will show the technology without complicating the example.

Step 1 Create a IRequest object

Objects that implement the IRequest interface represent Commands. Create a simple class called CommandExample like:

public class CommandExample : IRequest<bool>
    public bool NotMe { get; set; }

Step 2 Create a Handler

Handlers should implement IRequestHandler<in TRequest, out TResponse>. Where TRequest is the type of object we created in step 1 and TResponse is the type you want the handler to return.

So, for us, TRequest is CommandExample and as were negating the bool passed in, TResponse is bool. So create a new class called CommandExampleHandler:

public class CommandExampleHandler : IRequestHandler<CommandExample, bool>
    public bool Handle(CommandExample message)
        return !message.NotMe;

And thats it for the plumbing of MediatR. We have now implemented with command pattern.

But before this will work, we need to configure our DI container, in my case Ninject.

Ninject Configuration

I struggled with this as I couldnt find any clear examples. The project github repos has an example, but I couldnt get it to compile . When I finally did, it didnt work. I failed to use Ninject.Common.Extensions , but the below definitely works.

First, take a copy of

Then, in App_Start/NinjectWebCommon.cs add the following to RegisterServices

kernel.Components.Add<IBindingResolver, ContravariantBindingResolver>();

kernel.Bind<IRequestHandler<CommandExample, bool>>().To<CommandExampleHandler>();
kernel.Bind<SingleInstanceFactory>().ToMethod(ctx => t => ctx.Kernel.TryGet(t));
kernel.Bind<MultiInstanceFactory>().ToMethod(ctx => t => ctx.Kernel.GetAll(t));

Note the highlighted line. It is specific to the command and handler classes we created above. Change them for your classes if youre not following along.

All thats left is using our commands in our Web API 2 application.

Web API 2 controller

I intend to call mediator from within my controllers. It doesnt have to be there, but I like to keep thin controllers.

For this example, I updated the ValuesController. First, create a constructor that takes IMediator as an argument and sets a field.

private IMediator _mediator;

public ValuesController(IMediator mediator)
    _mediator = mediator;

Then, in my case, I updated the POST action method to

// POST api/values
public async void Post(CommandExample message)
    response = await _mediator.Send(message);

As you can see, we now have a nice thin controller. Note, the use of async and await.

Lets make sure it works.

Confirming It Works

This is where Swashbuckle comes in handy. Set a breakpoint in the POST action method and press F5. Navigate to http://localhost:<port>/swagger and expand Values and POST. Fill out the message like below

MediatR Swagger Post
MediatR Swagger Post

Click Try it out! and you should be able to step through the code. Travelling through your handler. And finally back to the controller to see the value passed in negated:


MediatR is a small library, but makes adding the command pattern to your .net projects simple. Getting Ninject working was a little harder than I expected, but nothing too hard. Give it a try and let me know if Im missing a trick.

Comments Section