Using ActionFilters in Dotnet Core Web API's

on
2 minute read

Manipulating the HttpContext generated by the dotnet Pipeline or playing with the request just before entering the action method sounds cool yeah?

Contain your enthusiasm and let me present you our friend mr. ActionFilter.

The dotnet request pipeline

Under the hood Dotnet serves requests using a pipeline model, where an incoming request is passed throug a series of filters and methods until it reached the Action Execution, wich represents our actual code.

When our code is completed this pipeline is unrolled in reverse order until the request exists to the outside world.

Quick pipeline diagram:

As you can see, before we reach our user code there are several steps where code can be executed using Filters and Middlewares, but those are not shown in this example as we’re going to view them in a later post.

ActionFilters, sync vs async

ActionFilters can be sync or async, depdending if we implement the IActionFilter or IAsyncActionFilter interface.

IActionFilter provides us with two diferents methods that fire before and after the Action Execution:

public class OurNotThatGoodOfAFilter : IActionFilter  
{  
    public void OnActionExecuting(ActionExecutingContext context)  
    {  
    }  

    public void OnActionExecuted(ActionExecutedContext context)  
    {  
    }  
}  

IAsyncActionFilter provides us with a single async method and an execution delegate. Our code will execute before or after the Action Execution depending on where it’s placed relative to the delegate await.

public class OurNotThatGoodOfAFilter : IActionFilter  
{  
        public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            await next();
        } 
}  

In practice we should choose between them depending on whether or not we’re going to call async methods.

Just keep in mind that you can implement both filters in a single class but the dotnet runtime will only call the async one and not execute the sync methods.

Using filters, register and invoke

To use our filter we need to register it into the IoC container and then we can invoke it in actions using the [ServiceFilter] attribute:

services.AddScoped<OurNotThatGoodOfAFilter>();
[ServiceFilter(typeof(OurNotThatGoodOfAFilter))]
[HttpGet("{id}")]
[ProducesResponseType(typeof(BroadcastModel), StatusCodes.Status200OK)]
public IActionResult Get(int id)
{
}