How can I do dependency injection in action filters in ASP.NET 4 RC WebAPI?

I use Windsor to manage IoC for my controllers in a WebAPI project. I have a DependencyResolver that works great for resolving dependencies with a controller, but now I'm looking to inject dependencies into a custom action filter that I use to manage authentication.

I studied the use of the custom ActionInvoker, but not the clear interface that uses the WebAPI, as I would like to move on to resolving property dependencies on the user action filter attribute before executing it. Does anyone have a good example of how to do this in MVC 4 RC?

EDIT: I know that you cannot inject constructor in filters because they are attributes and therefore created by an instance of the .NET framework, but I hope there will be some point in the execution life cycle that happens AFTER the filter, but before it is executed, where I can run some custom code to list the public properties of the filters and enter the necessary services.

+7
source share
2 answers

Action filters are attributes. In the .NET attribute, the instantiation process is controlled by the .NET runtime, and you do not control it. Thus, one of the possibilities is to use the Injection Dependency Injection , which I personally advise you about.

Another possibility is to use the marker attribute:

public class MyActionFilterAttribute : Attribute { } 

and then an action filter using the constructor insert:

 public class MyActionFilter : ActionFilterAttribute { private readonly IFoo _foo; public MyActionFilter(IFoo foo) { _foo = foo; } public override void OnActionExecuting(HttpActionContext actionContext) { if (actionContext.ActionDescriptor.GetCustomAttributes<MyActionFilterAttribute>().Any()) { // The action is decorated with the marker attribute => // do something with _foo } } } 

and then register it as a global action filter in Application_Start :

 IFoo foo = .... GlobalConfiguration.Configuration.Filters.Add(new MyActionFilter(foo)); 
+10
source

I had the same problem, but I decided to go for ServiceLocator (DependencyResolver.GetService) for this, since it is within the framework, as it seems to me, a valid approach

 public class RequiresSessionAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { var sessionService = (ISessionService) actionContext .ControllerContext.Configuration.DependencyResolver .GetService(typeof (ISessionService)); var sessionId = HttpUtility .ParseQueryString(actionContext.Request.RequestUri.Query) .Get("sessionId"); if (sessionId == null || !sessionService.IsValid(sessionId)) throw new SessionException(); base.OnActionExecuting(actionContext); } } 

and here is a test for this attribute, a bit of pain, but possible

 public class requires_sessionId { [Fact] void can_call_action_with_session_id() { var context = GetContext("http://example.com/?sessionId=blaa"); var sut = new RequiresSessionAttribute(); Assert.DoesNotThrow( () => sut.OnActionExecuting(context)); } [Fact] void can_not_call_action_without_session_id() { var context = GetContext("http://example.com/"); var sut = new RequiresSessionAttribute(); Assert.Throws<SessionException>( () => sut.OnActionExecuting(context)); } HttpActionContext GetContext(string url) { var sessionServiceMock = new Mock<ISessionService>(); sessionServiceMock .Setup(x => x.IsValid(It.IsAny<string>())) .Returns(true); var dependancyResolverMock = new Mock<IDependencyResolver>(); dependancyResolverMock .Setup(x => x.GetService(It.IsAny<Type>())) .Returns(sessionServiceMock.Object); var config = new HttpConfiguration { DependencyResolver = dependancyResolverMock.Object }; var controllerContext = new HttpControllerContext { Configuration = config, Request = new HttpRequestMessage( HttpMethod.Get, url) }; return new HttpActionContext { ControllerContext = controllerContext, }; } } 
+4
source

All Articles