Skip to main content

Filters

Level: Intermediate

ℹ️ Where This Fits

Filters are hooks around controller execution. Learn them after controllers, action results, and model binding because filters are mainly used with MVC/Web API controllers.

ℹ️ What You'll Learn
  • Filter definition: Code that runs before and/or after controller actions (cross-cutting concerns)
  • Cross-cutting concern: Code needed by many actions but not business logic (logging, auth, timing)
  • Authorization filters: Run first, check permissions, can short-circuit ([Authorize] attribute)
  • Resource filters: Run before model binding, before action (caching, validation)
  • Action filters: Run before and after action (logging request/response, modifying results)
  • Result filters: Run before/after result execution (result transformation)
  • Exception filters: Catch exceptions thrown by action (centralized error handling)
  • [Authorize] filter: Built-in, stops pipeline if user not authenticated, returns 401
  • [Authorize(Roles = "Admin")]: Only admins can execute this action
  • School Management filter examples: [LogActivity] logs action to audit table, [ValidateStudent] checks student exists
  • Global filters: Register in Program.cs, apply to all actions (error handling, logging)
  • Action filters with attributes: [ServiceFilter(typeof(LoggingFilter))] on specific actions
  • Filter order: Authorization → Resource → Action (before) → Handler → Action (after) → Result
  • Common use: Logging (what API was called, how long it took), caching (GET requests cache 5 minutes)
  • When not to use filters: Simple business logic (put in services), one-time validations (use action result checks instead)

What is a Filter?

A filter is code that runs before or after controller actions.

Example use cases:

  • log every API call
  • validate a custom header
  • handle exceptions
  • add response headers
  • measure execution time
  • check permissions

These are called cross-cutting concerns because they apply across many actions.

Filter Pipeline

For a controller action, ASP.NET Core can run filters around the action.

Simplified flow:

Request
-> Authorization filters
-> Resource filters
-> Action filters
-> Controller action
-> Result filters
-> Response

Exception filters can handle exceptions from action execution.

Types of Filters

Filter TypeRunsCommon Use
Authorization filterEarlyCheck access
Resource filterBefore model binding/actionCaching, short-circuiting
Action filterBefore and after action methodLogging, validation, timing
Exception filterWhen exception occursConvert exceptions to responses
Result filterBefore and after result executionModify response

Action Filter Example

💻 Try It — Console App
💡 Create a filter that logs action execution time.⌥ GitHub
using Microsoft.AspNetCore.Mvc.Filters;
using System.Diagnostics;

public class ExecutionTimeFilter : IActionFilter
{
private readonly ILogger<ExecutionTimeFilter> _logger;
private Stopwatch? _stopwatch;

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

public void OnActionExecuting(ActionExecutingContext context)
{
_stopwatch = Stopwatch.StartNew();
}

public void OnActionExecuted(ActionExecutedContext context)
{
_stopwatch?.Stop();

_logger.LogInformation(
"Action {ActionName} executed in {ElapsedMilliseconds} ms",
context.ActionDescriptor.DisplayName,
_stopwatch?.ElapsedMilliseconds);
}
}

This filter measures how long each action takes.

Register a Global Filter

builder.Services.AddControllers(options =>
{
options.Filters.Add<ExecutionTimeFilter>();
});

Global filters apply to all controllers and actions.

Register Filter Service

If your filter uses dependency injection, register it:

builder.Services.AddScoped<ExecutionTimeFilter>();

Then use it:

builder.Services.AddControllers(options =>
{
options.Filters.AddService<ExecutionTimeFilter>();
});

Use Filter on One Controller

[ServiceFilter(typeof(ExecutionTimeFilter))]
[ApiController]
[Route("api/students")]
public class StudentsController : ControllerBase
{
}

This applies the filter only to StudentsController.

Use Filter on One Action

[HttpGet("{id}")]
[ServiceFilter(typeof(ExecutionTimeFilter))]
public IActionResult GetStudent(int id)
{
return Ok();
}

This applies the filter only to one action.

Exception Filter Example

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

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

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

public void OnException(ExceptionContext context)
{
_logger.LogError(
context.Exception,
"Unhandled exception while executing {Path}",
context.HttpContext.Request.Path);

context.Result = new ObjectResult(new
{
message = "An unexpected error occurred."
})
{
StatusCode = StatusCodes.Status500InternalServerError
};

context.ExceptionHandled = true;
}
}

Important Note About Exception Handling

Exception filters work for MVC/controller action exceptions.

For application-wide exception handling, ASP.NET Core middleware is usually better:

app.UseExceptionHandler("/error");

Use filters when the concern is controller-specific.

Use middleware when the concern applies to the whole HTTP pipeline.

Custom Header Filter Example

Suppose internal school APIs require a custom header.

public class RequireSchoolHeaderFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.HttpContext.Request.Headers.ContainsKey("X-School-Code"))
{
context.Result = new BadRequestObjectResult(new
{
message = "X-School-Code header is required."
});
}
}

public void OnActionExecuted(ActionExecutedContext context)
{
}
}

Setting context.Result stops the action from running.

Filters vs Middleware

FeatureMiddlewareFilters
ScopeEntire request pipelineMVC/controller pipeline
Runs before routing?Can run before routingNo
Knows action details?Usually noYes
Best forGlobal HTTP concernsController/action concerns
ExamplesCORS, auth, static files, error handlingAction logging, result changes

Common Mistakes

MistakeBetter Approach
Putting business logic in filtersKeep business logic in services
Using filters for all error handlingPrefer middleware for global errors
Forgetting to register DI filtersRegister with services
Logging sensitive request dataLog only safe context
Using filters when middleware is clearerPick the correct pipeline level

Practice Task

Create an action filter:

  1. Name it ApiRequestLogFilter.
  2. Log action name before execution.
  3. Log status code after execution.
  4. Register it globally.
  5. Apply it only to StudentsController as a second version.

Quick Recap

QuestionAnswer
What are filters?Code that runs around controller actions
Common filter for before/after action?Action filter
Filter for action exceptions?Exception filter
Global HTTP concerns?Middleware is usually better
Controller-specific concerns?Filters are useful
🎯 Interview Favourite

Q: What are filters in ASP.NET Core?

Good Answer: "Filters are components that run before or after controller action execution. They handle cross-cutting concerns such as logging, authorization checks, result modification, and exception handling. Common filter types include authorization filters, action filters, result filters, exception filters, and resource filters. Filters can be registered globally, per controller, or per action. Middleware is better for application-wide pipeline concerns, while filters are better when action or controller context is needed."

🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on ASP.NET Core Filters. Try these prompts:

  • "Explain filters vs middleware in simple terms."
  • "Show me an action filter that logs execution time."
  • "When should I use an exception filter?"
  • "What are cross-cutting concerns in ASP.NET Core?"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

Next Article

-> Static Files and wwwroot

nexcoding.in