Constructor Injection for ASP.NET MVC Action Filters
Author: Fredrik Kalseth
9. April 2009 11:50
ASP.NET MVC’s action filters allow you to execute some code before/after an action in a declarative manner, manipulating what goes into or comes out of the action. In essence, they are what’s called aspects in Aspect Oriented Programming; a way of encapsulating crosscutting concerns into reusable components. For example, instead of this:
public ActionResult SomeActionWhichRequiresAuthentication()
{
if (!User.Identity.IsAuthenticated)
{
return RedirectToAction(«Login», «Authentication»);
}
else
{
// …
}
}
You’ll do this:
public ActionResult SomeActionWhichRequiresAuthentication()
{
// …
}
However, a problem with ASP.NET MVC’s action filters is that there’s no support for having an IOC container manage them, which means that if I need to do something more complicated that requires calling into a domain service/repository for example, I cannot get these injected easily. Jeremy Skinner has a solution which enables property injection, but what I really want is constructor injection.
Solution: The Proxy Pattern
What I came up with, was to build a filter proxy. Using it looks like this:
public ActionResult SomeActionWhichRequiresAuthentication()
{
// …
}
Internally, the FilterAttribute resolves the actual filter using the IOC container and forwards all its calls to it:
public class FilterAttribute : ActionFilterAttribute
{
private readonly Type _actionFilterType;
private IActionFilter _action;
public FilterAttribute(Type actionFilterType)
{
_actionFilterType = actionFilterType;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// resolve the action filter using the IOC container
var container = (ICanResolveDependencies) HttpContext.Current.ApplicationInstance;
_action = (IActionFilter)container.Resolve(_actionFilterType);
_action.OnActionExecuting(filterContext);
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
_action.OnActionExecuted(filterContext);
base.OnActionExecuted(filterContext);
}
}
This allows the IOC container to manage the instantiation and lifetime of the action filter. Note the assumption that the applications Application object (Global.asax) implements the ICanResolveDependencies interface, which essentially is an abstraction of the IOC container.
Comments
This post is also available in: English
4/9/2009 12:23:21 PM
Nice solution. Thanks for sharing.
Andrew Davey
4/10/2009 12:44:39 PM
Nice solution… but I think that having the ActionInvoker inject dependencies is a better solution.
If you make a use of ASP.NET MVC extensibility points you end up keeping out of the way all your own infrastructural code.
An example of how this was done is the the NinjectActionInvoker ( codeclimber.net.nz/…/…es-into-asp.net-mvc.aspx ).
Simone
4/10/2009 4:47:39 PM
@Simone The NinjectActionInvoker you refer to is only able to do property injection, not constructor injection. In my opinion, property injection should only ever be used for optional dependencies. I agree that my proxy solution is not optimal, though. The best would be if ASP.NET MVC had native IOC support for all its extensibility points (like FubuMVC).
Fredrik
4/10/2009 5:13:29 PM
There is another issue by wrapping it in another filter, it is not possible to pass the parameters values of the original filter, for ex how do you pass the roles if your Authorize filter was decorated with it?
Kazi Manzur Rashid
4/10/2009 5:17:46 PM
I actually moved away from using the property-injection approach that I blogged about to something very similar to this. Here’s an example:
sutekishop.googlecode.com/…/…UsingAttribute.cs
The only real difference is that it supports multiple filter types rather than just Action Filters.
Jeremy
Jeremy Skinner
4/10/2009 5:35:39 PM
Trackback from DotNetShoutout
Constructor Injection for ASP.NET MVC Action Filters – Fredrik Kalseth
DotNetShoutout
4/10/2009 8:39:26 PM
@Rashid Good question. The proxy could be refactored to take an anonymous object and use it to set properties on the filter. It wouldn’t be too pretty, though. Like I said, I really wish the MVC framework had a pluggable container at its core so we wouldn’t need to hack it like this
Fredrik
4/13/2009 2:59:20 AM
Trackback from 9eFish
Constructor Injection for ASP.NET MVC Action Filters
9eFish
4/18/2009 1:23:50 PM
Trackback from Faculty of The Mind
Constructor Injection for ASP.NET MVC Model Binders
Faculty of The Mind
4/27/2009 11:28:43 PM
Nice post…
Jones
5/12/2009 11:55:24 AM
Thank you for saving my day
squig
6/19/2009 8:34:02 PM
What about using «compile time weaving» techniques ?. I’ve registered the filter in the IoC container with its corresponding dependencies. The filter class has to be decorated with the attribute so the weaver (PostSharp) knows about. Whenever whoever instantiates the class the dependencies get wired.