In ASP.NET Core, filters give you a powerful way to inject logic at specific points in the MVC / Web API request pipeline. Instead of repeating the same code in every controller action (like logging, authorization checks, exception handling, or response wrapping), you can move that logic into reusable filters.
In this article, we’ll go through each filter type in detail, with:
What it does in the pipeline
A realistic use case (e.g., admin check, performance timing, global error handling)
A small code example
A line-by-line explanation so you can understand the syntax clearly
1. Authorization Filters
What is an Authorization Filter?
An Authorization Filter is the first filter that runs in the MVC pipeline. It executes before model binding and before the action, which makes it the ideal place to decide:
“Is this user allowed to call this action at all?”
If the user is not authorized, the filter can short-circuit the pipeline by returning a ForbidResult or UnauthorizedResult instead of letting the action execute.
Real-World Scenario
Imagine you have an Admin Dashboard where only users with the Admin role should be able to access. Instead of adding if !User.IsInRole("Admin")) ... in every action, you can create one authorization filter and apply it once.
Example – Custom Role Authorization Filter
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
public class RoleAuthorizationFilter : IAuthorizationFilter
{
private readonly string _role;
public RoleAuthorizationFilter(string role)
{
_role = role;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = context.HttpContext.User;
if (!user.Identity?.IsAuthenticated ?? true || !user.IsInRole(_role))
{
context.Result = new ForbidResult();
}
}
}Line-by-Line Explanation
RoleAuthorizationFilter : IAuthorizationFilter
This class implementsIAuthorizationFilter, which means ASP.NET Core will call itsOnAuthorizationmethod during the authorization stage.Private field
_roleand constructor
We inject a role name (e.g.,"Admin") via the constructor so this filter can be reused for multiple roles.OnAuthorization(AuthorizationFilterContext context)
This method is called automatically by the framework. Thecontextgives access to the currentHttpContext, the user, the route data, etc.var user = context.HttpContext.User;
Gets the current logged-in user (principal).Condition
if (!user.Identity?.IsAuthenticated ?? true || !user.IsInRole(_role))If the user is not authenticated OR not in the required role, we treat them as unauthorized.
context.Result = new ForbidResult();
Settingcontext.Resulttells ASP.NET Core:
“Do not continue the action. Return this result immediately.”
In this case, the user receives an HTTP 403 Forbidden.
Applying the Filter to a Controller
[ApiController]
[Route("api/[controller]")]
[TypeFilter(typeof(RoleAuthorizationFilter), Arguments = new object[] { "Admin" })]
public class AdminController : ControllerBase
{
[HttpGet("dashboard")]
public IActionResult GetDashboard()
{
return Ok("This is the admin dashboard.");
}
}Here:
[TypeFilter]tells ASP.NET Core to resolveRoleAuthorizationFilterfrom DI and pass"Admin"to its constructor.Any request to
/api/admin/dashboardmust be authenticated and in the"Admin"role; otherwise, the action never runs.
2. Resource Filters
What is a Resource Filter?
A Resource Filter runs after authorization but before model binding and action execution. It also runs again after the action and result are done.
It’s perfect for “outer-layer” concerns like:
Measuring how long a request took
Implementing custom caching
Preventing further processing if some header or condition is not met
Real-World Scenario
Suppose you want to know how long your API actions are taking in production. Instead of adding Stopwatch In every action, you create one Resource Filter and apply it globally or per controller.
Example – Request Timing Resource Filter
using Microsoft.AspNetCore.Mvc.Filters;
using System.Diagnostics;
public class RequestTimingResourceFilter : IResourceFilter
{
private Stopwatch _stopwatch;
public void OnResourceExecuting(ResourceExecutingContext context)
{
_stopwatch = Stopwatch.StartNew();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
_stopwatch.Stop();
var elapsedMs = _stopwatch.ElapsedMilliseconds;
Console.WriteLine($"Request took {elapsedMs} ms");
}
}Line-by-Line Explanation
RequestTimingResourceFilter : IResourceFilter
ImplementsIResourceFilter, so ASP.NET Core knows to call its resource stage methods.Private field
_stopwatch
Stores theStopwatchinstance for a single request.OnResourceExecuting(ResourceExecutingContext context)
Called before model binding and before the action method.
We start the stopwatch here:Stopwatch.StartNew().OnResourceExecuted(ResourceExecutedContext context)
Called after the action and result have been executed.
We stop the timer, get the elapsed milliseconds, and log to the console.
Applying It to a Controller
[ApiController]
[Route("api/[controller]")]
[TypeFilter(typeof(RequestTimingResourceFilter))]
public class ProductsController : ControllerBase
{
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
return Ok(new { Id = id, Name = "Sample Product" });
}
}Now every time /api/products/{id} is called:
The Resource Filter starts the stopwatch
The action executes
The filter logs how long it took
In a real project, you might log to Application Insights, Seq, or a database.
3. Action Filters
What is an Action Filter?
An Action Filter runs right before and right after the action method. This makes it ideal for logic closely tied to the action itself, such as:
Logging input parameters
Validating custom conditions
Modifying action results
Timing the action itself (not the whole request)
Real-World Scenario
Imagine you want to log every request’s incoming data for auditing. Instead of logging inside each controller action, you use an Action Filter that logs:
Action name
Parameter names and values
Example – Log Action Arguments Filter
using Microsoft.AspNetCore.Mvc.Filters;
public class LogActionArgumentsFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
foreach (var arg in context.ActionArguments)
{
Console.WriteLine($"Param: {arg.Key} = {arg.Value}");
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Optional: log something after the action executes
Console.WriteLine("Action executed.");
}
}
Comments
Join the conversation! Your thoughts help the community grow.