Diverse @no

Constructor-Injection-for-ASPNET-MVC-Action-Filters.aspx

Constructor Injection for ASP.NET MVC Action Filters

Author: Fredrik Kalseth

An entry about asp.net mvc | inversion of control Publication date 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.

Currently rated 3.3 by 9 people

  • Currently 3.333333/5 Stars.

Comments

4/9/2009 12:23:21 PM

Andrew Davey

Nice solution. Thanks for sharing.

Andrew Davey United Kingdom

4/10/2009 12:44:39 PM

Simone

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 Italy

4/10/2009 4:47:39 PM

Fredrik

@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 Norway

4/10/2009 5:13:29 PM

Kazi Manzur Rashid

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 United States

4/10/2009 5:17:46 PM

Jeremy Skinner

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 United Kingdom

4/10/2009 5:35:39 PM

trackback

Trackback from DotNetShoutout

Constructor Injection for ASP.NET MVC Action Filters – Fredrik Kalseth

DotNetShoutout

4/10/2009 8:39:26 PM

Fredrik

@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 Smile

Fredrik Norway

4/13/2009 2:59:20 AM

trackback

Trackback from 9eFish

Constructor Injection for ASP.NET MVC Action Filters

9eFish

4/18/2009 1:23:50 PM

trackback

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

Jones

Nice post…

Jones United States

5/12/2009 11:55:24 AM

squig

Thank you for saving my day Smile

squig Germany

6/19/2009 8:34:02 PM

javier

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.

This post is also available in: English

author-avatar

About Aksel Lian

En selvstendig full stack webutvikler med en bred variasjon av kunnskaper herunder SEO, CMS, Webfotografi, Webutvikling inkl. kodespråk..