.NET Core Web API - Filter Pipeline Overview
.NET Core Web API - Filter Pipeline Overview

Action Invocation Pipeline in ASP .NET Core Web APIs

In this article, let’s discuss about filter pipeline, a chain that executes between the routing middleware and the selected action.

What is it ?

In previous article, we have seen request process pipeline. The discussion mainly focused on middleware pipeline. It explained how a request flows through different middleware components to reach to the controller action.

But it was incomplete view. In the middleware pipeline, when routing middleware (UseEndpoints) dispatches the current incoming request to best matching endpoint, the request goes through a new chain, called as ASP .NET Core's action invocation pipeline.

This pipeline invokes filters which are applicable for current action and that’s why it is generally referred to as filter pipeline.

How does it work ?

Below is a diagram to explain how and where the filter pipeline comes into picture.

A request received by a .NET core web application goes through the middleware pipeline first. After routing middleware, request is dispatched to best matching endpoint for execution. But before reaching to the action, it goes through various stages of processing.

For each of these stage there is a logical name and an interface. For example, A result filter can implement IResultFilter and an action filter must implement IActionFilter or IAsyncActionFilter. Also, every stage interface has two methods

  • On{Stage}Executing (e.g. OnActionExecuting, OnResultExecuting, etc.)
  • On{Stage}Executed (e.g. OnActionExecuted, OnResultExecuted, etc.)

We will discuss about these interfaces later in details. Let’s first understand how and when different stages in filter pipeline are executed.

.NET Core Web API and Filter Pipeline

Authorization Filters

Authorization Filters to check if the user is authorized to perform this operation. If user is not authorized then these filter short circuit the pipeline, meaning, they return the result without reaching to next stages. This part is now shown in the diagram.

Also, note that exceptions raised by authorization filters would not be handled by exception filters as exception filters are not invoked in that case. So ideally, for short circuiting cases, authorization filter should consider sending error response (e.g. HTTP 401 unauthorized) instead of raising exceptions.

Resource Filters

Resource Filters are next to run in filter pipeline. OnResourceExecuting and OnResourceExecuted  are the methods implemented by resource filters.

Action Filters

After resource filters, model binding occurs. After model binding, Action filters are executed. Action filters implement either the IActionFilter or IAsyncActionFilter interface.

Action filters provides two methods OnActionExecuting and OnActionExecuted, which execute just before executing action and just after executing an action respectively. OnActionExecuted can be used to modify the result from action.

Exception Filters

Exception filters are executed after Action Filters , after action execution is done. These can be used to apply global exception handling policies before response has been written. Generally it might be good idea to use Exception Handler middleware rather than creating / using exception filters in most of the cases.

Result Filters

Result execution happens after exception filters (not shown in diagram above). Result execution is the step to write response which would be returned to the caller. Result filters have methods OnResultExecuting and OnResultExecuted, which runs before and after of executing result.

How to apply filters ?

There are three places where filters can be specified.

First way is to specify filters in Startup.ConfigureServices as shown in below code. Filters added like this are global and they are applicable to all endpoints.

Another way is to specify filter as an attribute on a controller. In this case, the filter is applicable to all actions in that controller. One of the sample is discussed here in this article.

Third and final way is to specify filter attribute on an action itself. So this filter would be applicable only to that particular action.

Order of Execution

General order of execution is shown in the image above. In case, when there are multiple filters specified at a given level, then those filters are executed based on their scopes.

So, global filters wrap the filter attributes specified on a controller class. And controller level attribute wrap the filters specified on individual actions.

So, let’s say there are action filters specified at all 3 scopes then below would be order of execution for action filter’s stage:

  • Before method of global filter
  • Before method of controller level filter
  • Before method of action level filter
  • Action execution
  • After method of action level filter
  • After method of controller level filter
  • After method of global level filter

Sync vs Async Interfaces

To identify which stage a filter belongs to, check the interfaces implemented by the filter. Every filter stage generally provides both synchronous version and async version of the interface. Generally, a filter is supposed to implement only one of these two interfaces.

For example, an action filter should implement either IActionFilter or IAsyncActionFilter, but not both.

But this is a recommendation and technically you do not get any error if both sync and async interfaces are implemented in same filter. As per documentation, filter pipeline prefers async interfaces from a filter if that filter implements both type of interfaces.

I hope you find this information useful. Let me know your thoughts.

Leave a ReplyCancel reply

This Post Has One Comment