Filters in ASP.NET Core MVC

Filters in ASP.NET Core MVC

In this article, I will discuss Filters in ASP.NET Core MVC Applications. Filters are one of the most important concepts in ASP.NET Core MVC Applications, and as a developer, we should be aware of this concept. So, from this and in a few upcoming articles, I will discuss ASP.NET Core MVC Filters in Detail. As part of this article, we will discuss the following pointers.

  1. What are Filters in ASP.NET Core MVC?
  2. Why are Filters in ASP.NET Core MVC?
  3. What are the Differences Between Filters and Middlewares in ASP.NET Core?
  4. Types of Filters in ASP.NET Core MVC
  5. Advantages and Disadvantages of Filters in ASP.NET Core MVC
  6. Where can we configure filters in ASP.NET Core MVC?
  7. Default Filters Execution Order in ASP.NET Core MVC
What are Filters in ASP.NET Core MVC?

In ASP.NET Core MVC, filters are fundamental to the framework’s request and response processing pipeline. Filters allow us to perform certain actions or execute logic before or after an HTTP request is handled by a controller action or after the response is generated but before it is sent to the client. Filters are used to add cross-cutting concerns, such as Logging, Authentication, Authorization, Exception Handling, Caching, etc., to our application in a modular and reusable way.

We have already discussed in Routing that when a client makes a request, that request comes to the Routing Engine, and then the Routing Engine navigates that Request to the Controller Action Method. So, the Controller action method will handle the incoming request and send the response back to the client who initially made the request, as shown in the image below.

What are Filters in ASP.NET Core MVC?

But what will you do if you want to execute some code or logic before or after the action method is executed, as shown in the image below?

What are Filters in ASP.NET Core MVC?

If that is your requirement, then you need to use Filters in your ASP.NET Core MVC application. The Filters in ASP.NET Core MVC are the attribute that allows us to inject some logic or code that will be executed before or after an action method is executed.

Why are Filters in ASP.NET Core MVC?

In ASP.NET Core MVC, Filters are used to perform cross-cutting concerns. They are as follows:

  • Caching
  • Logging
  • Error Handling
  • Modifying the Result
  • Authentication and Authorization, etc.
What are the Differences Between Filters and Middlewares in ASP.NET Core?

Filters and middleware are two distinct concepts in ASP.NET Core, and they serve different purposes within the request processing pipeline. Here are the key differences between filters and middleware:

Scope of Application:
  • Filters: Filters are primarily applied to individual controller actions or controllers. They are used to add specific behaviors or concerns to processing a single action or a group of actions within a controller.
  • Middlewares: Middlewares are applied to the entire application’s request processing pipeline. They operate at a lower level than filters and can handle requests and responses globally, regardless of the specific controller or action being invoked.
Execution Point:
  • Filters: Filters execute within the ASP.NET Core MVC framework’s pipeline and are part of the controller/action execution process. They are triggered before or after the execution of a specific action method.
  • Middlewares: Middlewares execute earlier in the request processing pipeline, typically before the request reaches the ASP.NET Core MVC framework. They can intercept requests and responses and perform tasks at various stages of the request processing pipeline, such as Routing, Authentication, Response Formatting, etc.
Purpose and Concerns:
  • Filters: Filters are designed for handling concerns specific to the ASP.NET Core MVC framework, such as Logging, Authentication, Authorization, Exception Handling, Caching, Custom Logic, etc.
  • Middlewares: Middlewares are more general-purpose and can handle many concerns, including Routing, Authentication, Request/Response Logging, Compression, Security, and Custom Processing not tied to the ASP.NET Core MVC framework.
Granularity:
  • Filters: Filters offer fine-grained control and customization at the level of individual actions or controllers. You can apply different filters to controllers and action methods based on your requirements.
  • Middlewares: Middlewares provide a broader, global view of the request processing pipeline. They are suitable for tasks that must be applied uniformly across all requests or specific stages of the request processing pipeline.
Configuration and Order:
  • Filters: Filters are typically configured using attributes (e.g., [Authorize], [AllowAnonymous], etc.) on controllers or action methods. You can also register global filters in the Startup or Program Class based on the .NET version you use to develop your ASP.NET Core Application. The execution order for filters is decided based on the type of filters you are applying to the controllers and action methods.
  • Middlewares: Middlewares are configured and ordered in the Startup (Configure method) or Program (Main method) class based on the .NET version you use to develop your ASP.NET Core Application. The execution order for middleware components is determined by the order in which they are added to the IApplicationBuilder pipeline, i.e., to the Request Processing Pipeline.
Access to HttpContext:
  • Filters: Filters can access the HttpContext object, which contains information about the current request and response. They can interact with controller action parameters and results.
  • Middlewares: Middlewares also have access to the HttpContext object but operate independently of the ASP.NET Core MVC framework. They can process requests and responses before they reach or leave the MVC Pipeline.

So, Filters and Middleware Components serve different purposes and have different scopes within an ASP.NET Core MVC application. Filters are more tightly integrated with the ASP.NET Core MVC framework and are applied at the controller/action level. In contrast, Middleware Components operate at a lower level, are applied globally to the entire application, and handle a wider range of concerns. The choice between Filters and Middleware Components depends on the specific requirements of your application and the level of customization and control you need for different aspects of the request processing pipeline.

Types of Filters in ASP.NET Core MVC

In ASP.NET Core MVC, there are several types of filters that you can use to add or modify the behavior in the request and response processing pipeline. These filters can be applied at various stages of the MVC framework’s Request/Response Processing Pipeline. The main types of filters in ASP.NET Core MVC include:

Authorization Filters in ASP.NET Core:

The Authorization Filters in the ASP.NET Core Application perform Authentication and Authorization checks before an action method is executed. Examples include AuthorizeAttribute for role-based or policy-based authorization and AllowAnonymousAttribute to allow unauthenticated users to access an action.

  • [Authorize]: This Built-in Filter restricts access to actions or controllers to authenticated users. You can specify Roles, Policies, or Individual users who can access specific resources.
  • [AllowAnonymous]: This Built-in Filter allows unauthenticated users to access actions or controllers even when the application has enabled global authentication.
  • Custom Authentication: You can also create Custom Authentication. To create Custom Authentication in ASP.NET Core MVC, you need to create a class implementing the IAuthorizationFilter interface and provide implementations for the OnAuthorization method, where you must write the custom authentication logic as per your business requirements.
Action Filters in ASP.NET Core:

The Action Filters in the ASP.NET Core MVC Application are executed before and after an action method is executed. They are used to perform tasks like Logging, Modifying the Action’s Arguments, or Altering the Action’s Result.

In ASP.NET Core, you can create a Custom Action Filter in two ways: First, by creating a class implementing the IActionFilter interface and providing implementations for [OnActionExecuting] and [OnActionExecuted] methods. Second, by creating a class inheriting from the ActionFilterAttribute class and overriding the [OnActionExecuting] and [OnActionExecuted] methods.

  • [ServiceFilter] or [ServiceFilter ]: The TypeFilter and ServiceFilter are built-in attributes in ASP.NET Core that apply Custom Filters to controller actions or controllers. You cannot apply Custom Action Filters (if they are not created as Attributes) directly to the controllers and action methods. To apply the custom action filters as an Attribute to the actions and controllers, we need to use TypeFilter and ServiceFilter as built-in attributes.
  • [OnActionExecuting] and [OnActionExecuted]: These are the two methods within a Custom Action Filter to execute logic before and after an action method is called. The OnActionExecuting method with a Custom Action Filter executes before the action method is invoked, and the OnActionExecuted method with a Custom Action Filter executes after the action method is invoked.
Result Filters in ASP.NET Core:

The Result Filters in ASP.NET Core MVC Application runs after the action method has been executed but before the result is processed and sent to the client. This means you can modify the view or the result data before it gets rendered to the response output. They are used for tasks such as Adding Headers to the response, Modifying the Result, etc.

In ASP.NET Core, you can create a Custom Result Filter in two ways: First, by creating a class implementing the IResultFilter interface and providing implementations for [OnResultExecuting] and [OnResultExecuted] methods. Second, by creating a class inheriting from the ResultFilterAttribute class and overriding the [OnResultExecuted] and [OnResultExecuted] methods.

  • [ResponseCache]: This Built-in Attribute controls caching behavior for the action result. 
  • [OnResultExecuting] and [OnResultExecuted]: These are the two methods within a Custom Result Filter to execute logic before and after the Result is generated. The OnResultExecuting method with a Custom Result Filter executes before the result is generated, and the OnResultExecuted method with a Custom Result Filter executes after the result is generated.
Exception Filters in ASP.NET Core:

The Exception Filters in the ASP.NET Core MVC Application are executed when an unhandled exception occurs during the execution of an action method. The Exception Filters are used for Logging, Error Handling, Custom Exception Processing, Displaying Different Error Pages Based on the Error Status Codes, etc.

In ASP.NET Core, you can create a Custom Exception Filter in two ways: First, by creating a class implementing the IExceptionFilter interface and providing implementations for the [OnException] method. Second, by creating a class inheriting from the ExceptionFilterAttribute class and overriding the [OnException] method.

Note: The Built-in Filters are part of the ASP.NET Core MVC framework and can be applied to our controllers and actions by decorating them with the appropriate filter attributes. You can also customize and extend these filters or create your own custom filters by implementing the corresponding filter interfaces (e.g., IActionFilter, IResultFilter, IExceptionFilter) or inheriting from the Filter Attributes (e.g., ActionFilterAttribute, ResultFilterAttribute, ExceptionFilterAttribute) to address specific application requirements. 

Where Can We Configure Filters in ASP.NET Core MVC?

In the ASP.NET Core MVC Application, we can configure filters to apply cross-cutting concerns such as Authentication, Authorization, Logging, Caching, and Exception Handling to our application at various levels. Filters can be configured in the following three places:

Configuring Filters at Controller Level:

We can apply filters at the controller level by using filter attributes directly on our controller classes. When we apply the Filter at the controller level, it will apply to all the actions of that controller. Example of applying filters at the controller level:

[Authorize] // Authorization filter applied at the controller level
public class HomeController : Controller
{
    public IActionResult Index()
    {
        // Action logic
    }
}
Configuring Filters at Globally:

We can configure filters globally in the Program or Startup classes based on the .NET Version you use to develop the application. By adding filters as services, we can ensure they are applied globally to all controllers and actions in our application. Example of configuring a global filter in Program.cs class file:

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(new MyGlobalFilter());
});
Action Method Level:

We can also apply filters directly to individual action methods within our controller by using filter attributes. This allows us to apply specific filters only to certain actions. Example of applying filters at the action method level:

public class MyController : Controller
{
    [MyCustomFilter] // Custom filter applied to this action
    public IActionResult MyAction()
    {
        // Action logic
    }
}
Default Filters Execution Order in ASP.NET Core MVC

In ASP.NET Core MVC, filters are executed in a specific order known as the “Default Execution Order.” The default execution order ensures that filters are applied consistently throughout the request processing pipeline. The default execution order, from the earliest to the latest in the pipeline, is as follows:

  • Authorization Filters: Authorization filters are executed first. They are responsible for checking whether the current user can access the requested resource or action. If authorization fails, the request may be short-circuited, and the action method is not executed.
  • Action Filters (Before Action Execution): Action filters with “Before Action Execution” logic are executed before the action method is invoked. These filters can perform tasks like logging, input validation, or pre-processing data.
  • Model Binding: Model binding occurs at this stage. It binds incoming data to action method parameters and executes model validation.
  • Action Execution: The action method itself is executed.
  • Action Filters (After Action Execution): Action filters with “After Action Execution” logic are executed after the action method completes its execution. These filters can perform tasks like logging, modifying the action result, or post-processing data.
  • Result Filters (Before Result Execution): Result filters with “Before Result Execution” logic are executed before the action result is executed. These filters can modify the result or perform additional processing.
  • Action Result Execution: The action result, which can be a view or any other result type, is executed.
  • Result Filters (After Result Execution): Result filters with “After Result Execution” logic are executed after the action result has been executed. These filters can perform tasks like logging or post-processing of the result.
  • Exception Filters (If an Exception Occurs): Exception filters are executed if an unhandled exception occurs during the processing of the request. These filters can handle the exception, log it, and return an appropriate error response.

Note: Please note that not all filters are executed for every request. The execution of certain filters depends on the specific request, filter attributes on controllers and actions, and other factors.

Filter Pipeline in ASP.NET Core MVC:

You can also customize the execution order of filters by setting the Order property when registering filters in the Program or Startup classes. This allows you to control the sequence in which filters are executed, especially when you have multiple filters of the same type. Lower-order values are executed earlier in the pipeline. You can configure this order by setting the Order property when configuring filters. Example of setting the filter order:

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(new MyFilter1() { Order = 1 });
    options.Filters.Add(new MyFilter2() { Order = 2 });
});
Advantages and Disadvantages of Filters in ASP.NET Core MVC

Filters in ASP.NET Core MVC Application provide several advantages and disadvantages. Understanding the advantages and disadvantages of Filters is essential for making decisions about when and how to use them in your application. Here are the advantages and disadvantages of Filters in ASP.NET Core MVC:

Advantages of Filters in ASP.NET Core MVC:
  • Modularity and Reusability: Filters in ASP.NET Core allow us to encapsulate and separate concerns in our application, which makes our code more modular and easier to maintain. We can define filters for specific requirements of our application (e.g., Authentication, Authorization, Logging, Exception Handling, etc.) and apply them selectively to controllers or actions. This also promotes code reusability as we defined the filter once and applied it at multiple places.
  • Cross-Cutting Concerns: Filters in ASP.NET Core provide a centralized and consistent way to handle cross-cutting concerns, such as Authentication, Authorization, Logging, Error Handling, Caching, etc, without duplicating code.
  • Customization and Extensibility: ASP.NET Core MVC Framework provides many built-in filters that we can use directly in our controllers and action methods. It also allows us to create Custom filters to address specific requirements unique to your application, which are not served by the built-in filters. 
  • Separation of Concerns: Filters in ASP.NET Core help us to maintain the separation of concerns principle in our application architecture. By applying filters to specific actions or controllers, we can ensure that each application component focuses on its primary responsibility, making the codebase more maintainable and easier to understand.
  • Consistency and Standardization: Filters in ASP.NET Core allow us to enforce consistent behavior and standards across our application. For example, we can use authorization filters to ensure that only authenticated users with specific roles can access certain actions. This consistency is especially important for security and compliance.
  • Performance Optimization: Filters in ASP.NET Core Application can also be used for performance optimization tasks, such as caching frequently used data or results. Result filters, for instance, allow us to cache the output of an action and serve it directly from the cache for subsequent requests, reducing the load on our application and improving response times.
  • Security: Filters in ASP.NET Core Application are essential for implementing security measures like authentication and authorization. Authorization filters can restrict access to specific actions or resources based on user roles, permissions, or policies, helping protect sensitive parts of our application.
  • Error Handling: Exception Filters in the ASP.NET Core Application help us to handle unhandled exceptions, allowing us to log errors, provide user-friendly error messages, and maintain the stability of our application, providing different error pages based on different status codes, etc.
  • Logging and Monitoring: Filters can also be used for logging important information about requests and responses, facilitating monitoring, debugging, and auditing of our application’s behavior.
Disadvantages of Filters in ASP.NET Core MVC:
  • Complexity: As filters can be applied at different levels (Action, Controller, Global), and multiple filters can be combined, it can lead to increased complexity in understanding the overall behavior of a controller or action. Once you understand the concepts, then it will not be a problem at all. Yes, initially, you will find it a little difficult to understand.
  • Ordering: Managing the execution order for multiple filters can be challenging, especially when filters with conflicting behaviors are applied to the same action.
  • Maintenance Overhead: While filters promote code Reusability and Modularity, at the same time, having many filters can also make your application difficult to understand, maintain, and debug. 
  • Performance Overhead: Filters add a slight performance overhead to request processing by introducing additional method calls and processing steps. However, this overhead is usually negligible for most applications.
  • Limited Scope: Filters operate within the ASP.NET Core MVC Framework’s Request Processing Pipeline and may not be suitable for handling tasks that require broader control over the entire request processing, such as low-level routing or response compression. In that case, you might use Middleware Components.

In the next article, I will discuss Exception Filter in ASP.NET Core MVC Application. Here, in this article, I try to explain Filters in ASP.NET Core MVC Applications with Examples. I hope you understand the need and use of Filters in ASP.NET Core MVC Applications.

Leave a Reply

Your email address will not be published. Required fields are marked *