CodeOath
← All posts
.NET Core / Web API70 min total · 19 parts

Building REST APIs with ASP.NET Core: Routing, Middleware, and Dependency Injection

Contents — Part 15 of 19: Filters: Cross-Cutting Logic Around Actions
Part 15 of 19 · ~1 min

Filters: Cross-Cutting Logic Around Actions

Filters run at specific points in the pipeline around action execution — a lighter-weight alternative to full middleware when the logic genuinely only concerns MVC/API actions (it has access to action arguments and results, which raw middleware does not):

public class LogActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        Console.WriteLine($"Executing {context.ActionDescriptor.DisplayName}");
    }
    public void OnActionExecuted(ActionExecutedContext context)
    {
        Console.WriteLine($"Executed {context.ActionDescriptor.DisplayName}");
    }
}

[ServiceFilter(typeof(LogActionFilter))]
[HttpGet]
public IActionResult Get() => Ok();
Filter typeRuns around
Authorization filtersBefore anything else — deciding if the request is allowed to proceed at all
Resource filtersBefore/after model binding — can short-circuit before binding even happens
Action filtersImmediately before/after the action method itself runs
Exception filtersOnly when an unhandled exception occurs inside an action
Result filtersImmediately before/after the action's result is executed (written to the response)

Global exception filters and middleware-based exception handling (previous section) overlap in purpose; the practical convention is middleware for truly app-wide, unhandled-anywhere error formatting, and exception filters for MVC-specific exception handling that needs access to action/controller context.