ASP.NET Core is a versatile and robust web application framework. It offers a comprehensive collection of capabilities for developing strong and scalable applications, with Action Filters being one of the essential aspects that increase its functionality. Action filters allow you to execute code before or after an action method is executed, allowing you to add cross-cutting concerns to your application. In this post, we will look at action filters in ASP.NET Core, learn about their different types, and how to develop custom filters to improve the functionality of your web application.

What exactly are Action Filters?
In ASP.NET Core, action filters are properties that can be applied to controller action methods to do pre- or post-processing. They enable you to add functionality that is executed before or after action methods are invoked. Cross-cutting concerns like as logging, authentication, caching, and others can be implemented via action filters.

There are five types of action filters in ASP.NET Core.

  • Authorization Filter
  • Resource Filter
  • Action Filter
  • Result Filter
  • Exception Filter

Filter for Authorization
An authorization filter is essential for enforcing authentication and authorisation rules in your web application. Authorization filters are commonly used to guarantee that only authenticated and authorized users have access to certain areas of your application. These filters are run before the action method, allowing you to validate the user's credentials and permissions before granting or denying access. They are an important part of implementing security and access control in ASP.NET Core applications.

Example
Assume you have a controller with an action method to which you wish to limit access based on user roles. In this scenario, we'll use an Authorization Filter to determine whether or not the user has a specified role before granting access to the action method.

First, define a custom Authorization Filter.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Http;
using System;

public class CustomAuthorizationFilter : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
    // Check if the user is in the "Admin" role
    if (!context.HttpContext.User.IsInRole("Admin"))
    {
        // If not, deny access and return a forbidden status
        context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
    }
}
}


Next, apply the CustomAuthorizationFilter to your action method.
[CustomAuthorizationFilter] // Apply the custom authorization filter
public IActionResult AdminOnlyAction()
{
// This action is only accessible to users in the "Admin" role
return View();
}


In this example, the CustomAuthorizationFilter is applied to the AdminOnlyAction method. When a user tries to access this action, the filter checks if they are in the "Admin" role using the IsInRole method. If the user is not in the "Admin" role, the filter sets the HTTP response status code to 403 Forbidden, denying access to the action.

Resource Filter

Resource Filters in ASP.NET Core are a type of action filter that allows you to perform actions that affect the entire HTTP request and response, such as modifying response headers or handling global exceptions. These filters execute before any other filter type (Authorization, Action, Result, and Exception filters) have access to the HTTP context and can influence the entire request processing pipeline.

  • Global Exception Handling: Resource filters can be used to handle exceptions that occur during the request processing pipeline. By implementing a resource filter for exception handling, you can catch and handle exceptions globally, providing a consistent way to log errors, display custom error pages, or perform other actions.
  • Response Modification: You can modify the response object, such as adding custom response headers, changing the status code, or altering the response content, using resource filters.
  • Request Preprocessing: Resource filters can perform actions at the beginning of the request pipeline, such as setting request-specific variables or performing other pre-processing tasks.
  • Global Logging: You can use resource filters for global logging to log information about incoming requests, response times, or other metrics that apply to the entire application.

Example
Let's create a simple resource filter that adds a custom response header to every response in your ASP.NET Core application. In this example, we'll add a "X-Custom-Header" to the response.

Create a custom resource filter.
using Microsoft.AspNetCore.Mvc.Filters;

public class AddCustomHeaderResourceFilter : IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
    // Code to execute before the action
    context.HttpContext.Response.Headers.Add("X-Custom-Header", "MyCustomValue");
}

public void OnResourceExecuted(ResourceExecutedContext context)
{
    // Code to execute after the action
}
}


You can do this in the ConfigureServices method.
services.AddMvc(options =>
{
options.Filters.Add<AddCustomHeaderResourceFilter>();
});

Now, this resource filter will be executed for every request in your ASP.NET Core application, and it will add the "X-Custom-Header" to the response headers.

Resource filters are a powerful way to perform global actions that apply to all requests and responses in your application, making them a valuable tool for tasks like global exception handling, response modification, and request preprocessing.

Action Filter

Action Filters in ASP.NET Core are attributes that allow you to add logic that runs before and after the execution of individual action methods in your controllers. These filters are used to perform tasks such as logging, input validation, modifying the action result, and more.

Example

Let's create a simple Action Filter to log the start and end of an action method.

Create a custom Action Filter.
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;

public class LogActionFilter : IActionFilter
{
private readonly ILogger<LogActionFilter> _logger;

public LogActionFilter(ILogger<LogActionFilter> logger)
{
    _logger = logger;
}

public void OnActionExecuting(ActionExecutingContext context)
{
    // This method runs before the action method
    _logger.LogInformation($"Action '{context.ActionDescriptor.DisplayName}' is starting.");
}

public void OnActionExecuted(ActionExecutedContext context)
{
    // This method runs after the action method
    _logger.LogInformation($"Action '{context.ActionDescriptor.DisplayName}' has completed.");
}
}

You can do this in the ConfigureServices method.
services.AddMvc(options =>
{
options.Filters.Add<LogActionFilter>();
});

Apply the Action Filter to a controller action method.
[ServiceFilter(typeof(LogActionFilter))] // Apply the filter to this action method
public IActionResult MyAction()
{
// Your action method logic
}


Now, whenever you call the MyAction method, the LogActionFilter will log the start and end of the action, providing you with a simple way to monitor the execution of your action methods.

Result Filter

Result Filters in ASP.NET Core are a type of action filter that executes code after an action method has been executed but before the result is processed and sent to the client. These filters are useful for modifying the response or result, adding custom headers, or performing actions related to the response before it is returned to the client.

Example
Let's create a simple Result Filter to add a custom header to the response.

Create a custom Result Filter.
using Microsoft.AspNetCore.Mvc.Filters;

public class AddCustomHeaderResultFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
    // This method runs before the result is executed
    context.HttpContext.Response.Headers.Add("X-Custom-Header", "MyCustomValue");
}

public void OnResultExecuted(ResultExecutedContext context)
{
    // This method runs after the result is executed
}
}

You can do this in the ConfigureServices method.
services.AddMvc(options =>
{
options.Filters.Add<AddCustomHeaderResultFilter>();
});

Apply the Result Filter to a controller action method.
[ServiceFilter(typeof(AddCustomHeaderResultFilter))] // Apply the filter to this action method
public IActionResult MyAction()
{
// Your action method logic
}


When you call the MyAction method, the AddCustomHeaderResultFilter will add the "X-Custom-Header" to the response headers before it's sent to the client. This can be useful for scenarios where you want to add custom response headers, set response content types, or perform other response-related actions.

Exception Filter

Exception Filters in ASP.NET Core are a type of action filter that are specifically designed to handle exceptions that occur during the execution of an action method. These filters allow you to define custom logic to gracefully handle and respond to exceptions, providing a way to centralize error handling and improve the user experience.

How Exception Filters Work?

Exception filters are executed when an unhandled exception is thrown during the execution of an action method. They intercept the exception before it propagates up the call stack and provide an opportunity to perform custom error handling.
Use Cases for Exception Filters

Custom Error Pages: Exception filters can redirect the user to custom error pages, displaying user-friendly error messages instead of the default error page.
Logging and Reporting: You can use exception filters to log exceptions, making it easier to identify and fix issues. You can also report exceptions to external systems for further analysis.
Graceful Degradation: In cases where an exception occurs but the application can still function to some extent, an exception filter can handle the error and return a partial or degraded response instead of a complete failure.

Example

Let's create a simple Exception Filter to log and handle exceptions.

Create a custom Exception Filter.
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;

public class CustomExceptionFilter : IExceptionFilter
{
private readonly ILogger<CustomExceptionFilter> _logger;

public CustomExceptionFilter(ILogger<CustomExceptionFilter> logger)
{
    _logger = logger;
}

public void OnException(ExceptionContext context)
{
    // Log the exception
    _logger.LogError($"An exception occurred: {context.Exception.Message}");

    // Handle the exception
    context.Result = new ViewResult { ViewName = "Error" };
    context.ExceptionHandled = true;
}
}


You can do this in the ConfigureServices method.
services.AddMvc(options =>
{
options.Filters.Add<CustomExceptionFilter>();
});


Apply the Exception Filter to a controller action method.
[ServiceFilter(typeof(CustomExceptionFilter))] // Apply the filter to this action method
public IActionResult MyAction()
{
// Your action method logic
}


If an unhandled exception occurs in the MyAction method, the CustomExceptionFilter will log the error and redirect the user to a custom error page.

Real-World Use Cases

Action filters are incredibly versatile and can be applied to a wide range of scenarios. Here are some real-world use cases for action filters in ASP.NET Core.

  • Logging: You can create an action filter that logs information about the execution of action methods, helping with debugging and monitoring.
  • Validation: Implement input validation checks before an action method is executed to ensure that the input data is valid.
  • Caching: Use action filters to cache the results of action methods to improve performance and reduce database or API calls.
  • Security: Implement security checks and authorization logic using action filters to restrict access to certain action methods based on user roles and permissions.
  • Exception Handling: Create custom exception filters to handle and log exceptions in a consistent and user-friendly manner.