Wednesday 7 November 2012

WebAPI ActionFilter Dependency Injection with StructureMap

This is a guide to performing dependency injection on a WebAPI ActionFilter. Specifically, an ActionFilter that implements System.Web.Http.Filters.ActionFilterAttribute, as this is designed to work on classes implementing ApiController and the methods of those classes. The IoC container library in this case is StructureMap.

Firstly, define your ActionFilter with its dependencies as properties with public setters. In this example our ActionFilter has a dependency on RavenDB's IDocumentStore. The purpose of the ActionFilter is to apply Aggressive Caching to the IDocumentStore.


We then need to write a custom IFilterProvider (again, of the System.Web.Http.Filters namespace) in order to provide us with ActionFilters with fully resolved dependencies. Our IFilterProvider uses the StructureMap container to 'build up' the ActionFilter's property dependencies via their public setter.

Our custom IFilterProvider also implements ActionDescriptorFilterProvider. This is the default IFilterProvider that asp.net will use if none other is specified. It is necessary because we need access to the GetFilters() method to return us the instantiated ActionFilters needed for the request. We then take each instantiated ActionFilter and pass it to StructureMap to inject the dependencies.


We then configure StructureMap to use our implementation of IFilterProvider when an instance is needed to create ActionFilters. What's interesting here is that we are using StructureMap to provide us with an implementation of something that will then do further dependency resolution for us.

Lastly, we also need to tell StructureMap which property types it should be looking to resolve dependencies for with public setters. All this configuration lives in the single StructureMap initialization step, but it is arguable that this should be done in the originating interface assembly IoC configuration.


Then we are able to decorate any ApiController implementation class or method with our AggresivelyCacheFor ActionFilter wherever we need Aggressive Caching on our IDocumentStore  Happy ActionFiltering!


4 comments:

  1. This is of very limited usefulness without the code. Do you have an implementation of it?

    ReplyDelete
    Replies
    1. The code is presented via a GitHub Gist. If you cannot see the code I can only assume GitHub has failed to serve it or that you have javascript disabled? The Gist can be found here https://gist.github.com/blair55/4034984

      Delete
  2. I would like to, instead of DocumentStore, inject a function. Something like >. I thought this approach would work like a charm, but I can't wire it together. As a side note, i pit a breakpoint in SmFilterProvider.GetFilters, but it is never hit.

    Any ideas? Thank you.

    ReplyDelete