Integrating MediatR with Web API

One of the design goals I had in mind with MediatR was to limit the 3rd party dependencies (and work) needed to integrate MediatR. To do so, I only take a dependency on CommonServiceLocator. In MediatR, I need to resolve instances of request/notification handlers. Rather than build my own factory class that others would need to implement, I lean on CSL to define this interface:

public interface IServiceLocator : IServiceProvider
{
    object GetInstance(Type serviceType);
    object GetInstance(Type serviceType, string key);
    IEnumerable<object> GetAllInstances(Type serviceType);
    TService GetInstance<TService>();
    TService GetInstance<TService>(string key);
    IEnumerable<TService> GetAllInstances<TService>();
}

But that wasn’t quite enough. I also wanted to support child/nested containers, which meant I didn’t want a single instance of the IServiceLocator. Typically, when you want a component’s lifetime decided by a consumer, you depend on Func<Foo>. It turns out though that CSL already defines a delegate to provide a service locator, aptly named ServiceLocatorProvider:

public delegate IServiceLocator ServiceLocatorProvider();

In resolving handlers, I execute the delegate to get an instance of an IServiceLocatorProvider and off we go. I much prefer this approach than defining my own yet-another-factory-interface for people to implement. Just not worth it. As a consumer, you will need to supply this delegate to the mediator.

I’ll show an example using StructureMap. The first thing I do is add a NuGet dependency to the Web API IoC shim for StructureMap:

Install-Package StructureMap.WebApi2

This will also bring in the CommonServiceLocator dependency and some files to shim with Web API:

image

I have the basic building blocks for what I need in order to have a Web API project using StructureMap. The next piece is to configure the DefaultRegistry to include handlers in scanning:

public DefaultRegistry() {
    Scan(
        scan => {
            scan.TheCallingAssembly();
            scan.AssemblyContainingType<PingHandler>();
            scan.WithDefaultConventions();
			scan.With(new ControllerConvention());
            scan.AddAllTypesOf(typeof(IRequestHandler<,>));
            scan.AddAllTypesOf(typeof(IAsyncRequestHandler<,>));
            scan.AddAllTypesOf(typeof(INotificationHandler<>));
            scan.AddAllTypesOf(typeof(IAsyncNotificationHandler<>));
        });
    For<IMediator>().Use<Mediator>();
}

This is pretty much the same code you’d find in any of the samples in the MediatR project. The final piece is to hook up the dependency resolver delegate, ServiceLocatorProvider. Since most/all containers have implementations of the IServiceLocator, it’s really about finding the place where the underlying code creates one of these IServiceLocator implementations and supplies it to the infrastructure. In my case, there’s the Web API IDependencyResolver implementation:

public IDependencyScope BeginScope()
{
    IContainer child = this.Container.GetNestedContainer();
    return new StructureMapWebApiDependencyResolver(child);
}

I modify this to use the current nested container and attach the resolver to this:

public IDependencyScope BeginScope()
{
    var resolver = new StructureMapWebApiDependencyResolver(CurrentNestedContainer);

    ServiceLocatorProvider provider = () => resolver;

    CurrentNestedContainer.Configure(cfg => cfg.For<ServiceLocatorProvider>().Use(provider));
    
    return resolver;
}

This is also the location where I’ll attach per-request dependencies (NHibernate, EF etc.). Finally, I can use a mediator in a controller:

public class ValuesController : ApiController
{
    private readonly IMediator _mediator;

    public ValuesController(IMediator mediator)
    {
        _mediator = mediator;
    }

    // GET api/values
    public IEnumerable<string> Get()
    {
        var result = _mediator.Send(new Ping());

        return new string[] { result.Message };
    }

That’s pretty much it. How you need to configure the mediator in your application might be different, but the gist of the means is to configure the ServiceLocatorProvider delegate dependency to return the “thing that the framework uses for IServiceLocator”. What that is depends on your context, and unfortunately changes based on every framework out there.

In my example above, I’m preferring to configure the IServiceLocator instance to be the same instance as the IDependencyScope instance, so that any handler instantiated is from the same composition root/nested container as whatever instantiated my controller.

See, containers are easy, right?

(crickets)

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in MediatR. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Will this work with Windsor?

  • Danny

    Jimmy,

    In my API controllers I see alot of API specific actions such as setting custom headers (pagination meta data headers for instance), returning appropriate HTTP status codes (404 when the resource could not be found, 403 when access to a resource is forbidden, sometimes a 400 (bad request)), etc…

    I understand you can factor authorisation checks out of your handlers, but for access checks this is more problematic because the easiest, most performant and most safe place is inline with your controller code.

    Would you advice to just throw exceptions in your handler and have your ‘API layer’ convert them to the appropriate HTTP response?

    • GuyHarwood

      we implement a decorator for this and have the IOC container decorate each handler. cross cutting concerns etc…

      You can read more about that type of approach here https://cuttingedge.it/blogs/steven/pivot/entry.php?id=91

      it doesn’t use authorisation as an example, but the approach is just the same

      • Danny

        Decorators are a great solution when you are indeed dealing with cross-cutting concerns: transactions, logging, general authorisation, etc…

        But in the case of my access checks:
        1. I don’t want to separate the checking of the access from my handler for safety reasons. It is easy to forget you might need additional access checks when changing what a handler does.

        2. I don’t want to fetch entities multiple times from my database for performance reasons. My handler tries to load entities as performant as possible (as to reduce lazy loading & N+1 problems, etc…) A possible access check decorator doesn’t know this so effectively I have to fetch the same object 2 times; 1 time for the access check and 1 time for the handler logic… A cache isn’t going to help me (since EF doesn’t support it)

        As an example, my code looks like this:

        var aggrageRoot = _repository.FindById(rootId).Include(x => x.SomeEntity).Include(x => x.SomeCollection)

        if (aggregateRoot == null) { // 404 NOT FOUND }

        var someObj = aggregateRoot.SomeCollection.SingleOrDefault(x => x.Id == id)

        if (someObj == null) { // 404 NOT FOUND }

        if (!CurrentUser.CanAccess(someObj)) { // 403 FORBIDDEN }

        // meat of the handler here

        • GuyHarwood

          point 1 – then it belongs in the handler
          point 2 – you could have an outer decorator that checks the cache for the object before loading from db. It will only reach that decorator if the inner auth decorator ran successfully.

  • hope it’s good news for us

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1782()

  • Sam

    We used this for AutoFac

    builder.RegisterAssemblyTypes(typeof(IMediator).Assembly).AsImplementedInterfaces();

    var container = new Lazy(() => builder.Build());

    var resolver = new Lazy(() => new AutofacWebApiDependencyResolver(container.Value));

  • Ayesha Ahmed

    All friends if you are geting bored then i have a very nice chat room where you can find pakistani girls, Indian Girls, Uae Girls, Uk Girls, Adult Girls, Dating Girls, Canada Girls, Islambad Grisl, Multan Girls Chat Room, If You Wana Join This Chat Room Then You Do Not Need Any Typ Of Registration Just Enter Your Nick And Enjoy A Pakistani Chat Rooms

  • Allen Firth

    Jimmy, when will MediatR 2 come out of pre-release on nuget? Please please please!!!

    • jbogard

      Not my choice, when .NET Core comes out of pre-release

  • Daniel Lorenz

    Doesn’t this style result in Service Locator pattern being used here?

    • jbogard

      How so?

      • Daniel Lorenz

        Aren’t you using the IoC container to pull out the correct handler? If you created an instance manually, you’d new up a new Mediatr and it would crash since the caller wouldn’t know the true dependency that is required for it to match up the right handler?

        • jbogard

          This is a little bit of a special case, but since I’m injecting the IMediator, and the IMediator has its dependency injected in the factory function, and the factory function itself is the contextual scoped container, it’s not service location.

          And if it’s a pedantic definition then who cares, this is a very common pattern to resolve at runtime an IFoo dependency based on any generic T (see auto-factory features of containers)

          • Daniel Lorenz

            The problem is that you would know what the generic type actually is in this scenario. This just makes it so you don’t have to inject all those handlers manually. The problem is that this ends up making a short cut where you now lost what those dependencies actually are. This just moves the root down a level, but it isn’t registering its own types here. It is still pulling from the original container? I might be overthinking this, but I try to avoid anything similar Service Locator like the plague. :)

          • jbogard

            That’s….the whole point here. Instead of me depending even on IHandler, I’m depending on something that can manage the entire request pipeline. In MediatR, I even allow for additional pipeline steps and build the entire chain of things that execute. Same thing for many other IFoo libraries, like FluentValidation etc. The “root” is not down a level, it’s up at the request level. For example, in ASP.NET Core, there is a service scope per request that is my composition root. I’m resolving from the injected composition root.

            Contrast this with static service location, that reaches *outside* the context boundary. If I’m resolving from a scoped context/container, I don’t see it as service location. It’s just using resolving vs. direct injection for handler instances.

          • Daniel Lorenz

            How is this different than just IoC injecting the container itself and calling GetInstance or whatever directly, other than having a direct dependency on a container? I always thought the Service Locator issue dealt with not knowing what the class truly depends on. Sure, you could say you are depending on IMediatr and calling .Send is what your true dependency is, but it isn’t really as straight forward as that. Someone has to know they need to setup their IoC container to support all those IHandler instances and not just the Mediatr instance. Unless you are saying that Mediatr is just abstracting the IoC container it is calling since it is setup in the IoC root? But even then, the end result is still asking for the implementation without it just being pushed into the constructor directly.

          • Matthew Morgan

            I think fully falling into the Service Locator anti-pattern depends on what you do with your factory. I happened to use Autofac to generically map my handlers to the appropriate command. Only one handler will be bound at a time and if the handler doesn’t exist, you’re right, it won’t get caught at compile time. It is, essentially, a service locator pattern – I won’t defend that much. It’s a calculated decision – I could write unit tests that validate my class convention, or very explicitly map my handlers in Autofac. In fact, using DI pretty much means you have to live with the potential of run-time only errors due to missing concrete classes in your container; doesn’t matter where you do the injection. I think the important thing here is to understand the fallacy and mitigate as many of the consequences. What I’m gaining are a set of commands that could be reused in a different context; my domain logic isn’t coupled to ASP.NET. It helps my controllers take a back set and make it easier to test / reuse important domain functions without having to worry about where that pesky HttpContext is going to come from.

          • Daniel Lorenz

            If you inject the command handler directly you know what you need to setup for DI to work. If you use imediatr you don’t necessarily know what to setup. I understand that it makes the code simpler but so does service locator in general. It just makes maintenance and testability much harder. If you don’t know the types at compile time it totally makes sense to do it this way, but in this case we know the exact dependency. This is essentially enabling lazy coding by developers. The extra layer is doing nothing but look up the type that you already know. Just make each controller handle 1 command and this all becomes unnecessary.

          • jbogard

            So I haven’t found any of your assertions to be true, in practice.

            And no, I still don’t think it’s service location. It’s not much different than Func, which is a factory method that delays the build of a dependency.

            The benefits of a single interface to push requests through (rather than depend directly on an implementation) mean I can build more intelligence into what it means to send a request. I’ve used this pattern now for…8 years? without the downsides you’ve mentioned coming up.

          • Daniel Lorenz

            I would be surprised that anything you add in the send call wouldn’t be better served by A decorator. I know in practice this probably isn’t a huge concern since it is at the top level of everything and you are probably the only consumer of the controllers. I am just making a more purist observation that you may not have noticed. Func gives you back an instance of what you would expect. Instead this takes one type parameter to build up an entirely different interface to use which can be confusing if you are new to it all. That is a big difference to me. Please don’t feel like I’m trying to be mean here! I really want to use this approach and I want you to convince me that I am either wrong or am right but the flexibility outweighs any downsides. ☺

          • jbogard

            So one big distinction is IHandler means “I depend on a handler” vs. IMediator means “I depend on something that mediates a request to something”. When you have a single pinch point, a uniform interface, now your options open to being able to layer more behaviors. In fact, that’s what I did with the MediatR pipeline, you don’t just decorate, you layer into a pipeline. That was quite a bit harder with decorators (assuming your container even supported it).

            For us, testing improved quite a bit too since we didn’t test handlers directly but sending requests. It moved our understanding away from implementations of handlers and up to sending of requests.

          • Daniel Lorenz

            How does it know when to return something for a query vs not for a command? When you add to the pipeline is it forced to run for all queries and command alike? I guess I should just look into the details of it.

          • jbogard

            It’s all IRequest so whatever you decide to do for that is what it does.

          • Daniel Lorenz

            Ah I have to have a base dependency on your interfaces instead. I was trying to avoid outside dependencies in my common class with all the handlers. SimpleInjector makes setting up decorators easy.