Search code examples
c#asp.netasp.net-mvcasp.net-coreaction-filter

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?


Solution

  • 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.