Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Action Filters with Dependency Injection in ASP.NET CORE?

I use constructor-based dependency injection everywhere in my ASP.NET CORE application and I also need to resolve dependencies in my action filters:

public class MyAttribute : ActionFilterAttribute {     public int Limit { get; set; } // some custom parameters passed from Action     private ICustomService CustomService { get; } // this must be resolved      public MyAttribute()     {     }      public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)     {         // my code         ...          await next();     } } 

Then in Controller:

[MyAttribute(Limit = 10)] public IActionResult() {     ... 

If I put ICustomService to the constructor, then I'm unable to compile my project. So, how do I supossed to get interface instances in action filter?

like image 558
James Smith Avatar asked Aug 31 '16 18:08

James Smith


People also ask

What is action filter in ASP.NET Core?

Action filters – They run right before and after the action method execution. Exception filters – They are used to handle exceptions before the response body is populated. Result filters – They run before and after the execution of the action methods result.


2 Answers

If you want to avoid the Service Locator pattern you can use DI by constructor injection with a TypeFilter.

In your controller use

[TypeFilter(typeof(MyActionFilterAttribute), Arguments = new object[] {10})] public IActionResult() NiceAction {    ... } 

And your ActionFilterAttribute does not need to access a service provider instance anymore.

public class MyActionFilterAttribute : ActionFilterAttribute {     public int Limit { get; set; } // some custom parameters passed from Action     private ICustomService CustomService { get; } // this must be resolved      public MyActionFilterAttribute(ICustomService service, int limit)     {         CustomService = service;         Limit = limit;     }      public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)     {         await next();     } } 

For me the annotation [TypeFilter(typeof(MyActionFilterAttribute), Arguments = new object[] {10})]seems to be awkward. In order to get a more readable annotation like [MyActionFilter(Limit = 10)]your filter has to inherit from TypeFilterAttribute. My answer of How do I add a parameter to an action filter in asp.net? shows an example for this approach.

like image 151
Ralf Bönning Avatar answered Oct 15 '22 10:10

Ralf Bönning


You can use Service Locator:

public void OnActionExecuting(ActionExecutingContext actionContext) {      var service = actionContext.HttpContext.RequestServices.GetService<IService>(); } 

Note that the generic method GetService<> is an extension method and lives in namespace Microsoft.Extensions.DependencyInjection.

If you want to use constructor injection use TypeFilter. See How do I add a parameter to an action filter in asp.net?

like image 35
adem caglin Avatar answered Oct 15 '22 12:10

adem caglin