One of the new features of the Dependency Inject (DI) components from MVC3 is something called a IFilterProvider. The purpose of this component is to provide a simpler way for MVC applications to interact with filters (action, exception, result, etc.). In the previous versions, trying to achieve something like providing DI support to filters was doable, it just required deeper integration into the MVC runtime. The IFilterProvider interface is defined as:
As you can see, it’s a pretty simple interface that can enable lots of opportunities if used in the right context. The MVC bits ship with an implementation named FilterAttributeFilterProvider that parses the attributes defined on actions and controllers and returns an aggregated list for the runtime to process. So, how can we leverage this class to provide DI to these attributes? Let’s take a look :)
Injecting Dependencies into Attributes
For this sample, I will use Ninject as the DI container to inject, via properties, dependencies into the attributes. The dependency is a simple IMessageService:
And it’s consumed by the MessageAttribute class:
The MessageAttribute class is using Ninject’s Inject attribute to inform the container that IMessageService needs to be injected as a property; in other words, inject after the creation of the attribute. From this point, all we need to allow for the injection to happen – this is where FilterAttributeFilterProvider comes into play with a few minor tweaks:
By overriding the GetFilters method and using the IKernel instance that has the IMessageService (or any other) registration, all of the work can be contained within the InjectableFilterProvider class. This allows us to easily re-use this provider within any MVC3 application (that uses Ninject of course!) and provide DI support to any attributes for any controller. From here, all we need to do is register the filter and pass it the correct container instance:
As you can see these new DI features within MVC3 make things that used to be hard (or awkward) pretty straightforward with minimal work. Feel free to check out the full sample out on Github and leave any questions as comments!