π¬ ASP.NET Filters: The Security Guards of Your Web App
Imagine a movie theater with different checkpoints. Before you watch the movie, guards check your ticket, your bag, and make sure youβre not bringing in outside food. ASP.NET Filters work the same wayβtheyβre checkpoints that run before, during, or after your code does its job!
π What Are Filters?
Think of your web app as a theme park. Visitors (requests) want to ride the roller coasters (your actions). But before they can ride, they pass through checkpoints:
- π« Ticket checker (checks if allowed in)
- π Bag inspector (prepares things)
- π¨ Emergency responder (handles problems)
- πΈ Photo booth (adds finishing touches)
Filters are these checkpoints! They run automatically at specific moments without you calling them directly.
π― The Filter Family: 4 Types
graph TD A["Request Arrives"] --> B["π Resource Filter"] B --> C["β‘ Action Filter"] C --> D["Your Code Runs"] D --> E["π¦ Result Filter"] E --> F["Response Sent"] D -->|Error!| G["π¨ Exception Filter"] G --> F
1οΈβ£ Action Filters: The Before & After Guards
Simple Idea: Action filters run right before and right after your main code (action) runs.
πͺ Real-Life Example
Like a referee in a soccer game:
- Before the play: βEveryone ready? Go!β
- After the play: βThat was a goal!β
π Code Example
public class LogActionFilter : IActionFilter
{
public void OnActionExecuting(
ActionExecutingContext context)
{
// BEFORE: Log when action starts
Console.WriteLine("Action starting!");
}
public void OnActionExecuted(
ActionExecutedContext context)
{
// AFTER: Log when action ends
Console.WriteLine("Action finished!");
}
}
π― When to Use
- β Logging who visited what page
- β Validating input data
- β Timing how long actions take
2οΈβ£ Exception Filters: The Emergency Handlers
Simple Idea: When something goes BOOM π₯ (an error), exception filters catch it and handle it gracefully.
πͺ Real-Life Example
Like a safety net under trapeze artists. If they fall, the net catches them safely!
π Code Example
public class HandleErrorFilter : IExceptionFilter
{
public void OnException(
ExceptionContext context)
{
// Catch the error
var error = context.Exception.Message;
// Show friendly message instead
context.Result = new ObjectResult(
new { error = "Oops! Something broke." }
);
// Mark as handled
context.ExceptionHandled = true;
}
}
π― When to Use
- β Showing friendly error pages
- β Logging errors for developers
- β Sending error alerts
3οΈβ£ Result Filters: The Final Touch Artists
Simple Idea: Result filters run right before and right after the result (response) is created.
πͺ Real-Life Example
Like a gift wrapper at a store. Your gift (data) is ready, but they add the pretty bow (extra formatting)!
π Code Example
public class AddHeaderFilter : IResultFilter
{
public void OnResultExecuting(
ResultExecutingContext context)
{
// BEFORE result: Add custom header
context.HttpContext.Response.Headers
.Add("X-Custom", "Hello!");
}
public void OnResultExecuted(
ResultExecutedContext context)
{
// AFTER result: Log it was sent
Console.WriteLine("Result sent!");
}
}
π― When to Use
- β Adding response headers
- β Modifying the final output
- β Caching responses
4οΈβ£ Resource Filters: The First & Last Checkpoint
Simple Idea: Resource filters run first (before everything) and last (after everything). They wrap the entire process!
πͺ Real-Life Example
Like the main gate of a castle. You pass through it first when entering and last when leaving!
π Code Example
public class CacheFilter : IResourceFilter
{
public void OnResourceExecuting(
ResourceExecutingContext context)
{
// FIRST: Check if we have cached result
var cached = GetFromCache(context);
if (cached != null)
{
// Skip everything, return cached!
context.Result = cached;
}
}
public void OnResourceExecuted(
ResourceExecutedContext context)
{
// LAST: Save to cache for next time
SaveToCache(context.Result);
}
}
π― When to Use
- β Caching (save and reuse results)
- β Short-circuiting (skip everything if needed)
- β Resource management
π οΈ Creating Custom Filters
Making your own filter is like building your own checkpoint!
π― Three Ways to Create
Way 1: Implement Interface
public class MyFilter : IActionFilter
{
public void OnActionExecuting(...) { }
public void OnActionExecuted(...) { }
}
Way 2: Inherit from Attribute
public class MyFilter : ActionFilterAttribute
{
public override void OnActionExecuting(
ActionExecutingContext context)
{
// Your logic here
}
}
Way 3: Use It Anywhere!
// On a single action
[MyFilter]
public IActionResult GetData() { }
// On a whole controller
[MyFilter]
public class HomeController { }
// On ALL controllers (global)
services.AddControllers(options =>
{
options.Filters.Add<MyFilter>();
});
βοΈ Filters vs Middleware: Whatβs the Difference?
Both are checkpoints, but they work at different levels!
graph TD A["Request"] --> B["Middleware 1"] B --> C["Middleware 2"] C --> D["Routing"] D --> E["π― Filters Start Here"] E --> F["Your Controller"] F --> G["Response"]
π Pizza Shop Analogy
| Middleware | Filters |
|---|---|
| πͺ The building entrance | π The kitchen area |
| Checks ALL visitors | Checks only customers ordering pizza |
| Runs for every request | Runs only for controller actions |
| No access to action details | Knows which action is running |
π Quick Comparison
| Feature | Middleware | Filters |
|---|---|---|
| Scope | All requests | Controller actions only |
| Order | Runs first | Runs after routing |
| Access | Basic HTTP | Full MVC context |
| Use For | Logging, Auth, CORS | Validation, Caching |
π― When to Use What?
Use Middleware When:
- β Logging all requests
- β Authentication for whole app
- β Adding headers to all responses
Use Filters When:
- β Validating action parameters
- β Handling action-specific errors
- β Caching specific actions
π The Complete Flow
Hereβs how everything runs in order:
graph TD A["π₯ Request"] --> B["Middleware Chain"] B --> C["Routing"] C --> D["π Resource Filter - Before"] D --> E["β‘ Action Filter - Before"] E --> F["π¬ Your Action"] F --> G["β‘ Action Filter - After"] G --> H["π¦ Result Filter - Before"] H --> I["Result Executes"] I --> J["π¦ Result Filter - After"] J --> K["π Resource Filter - After"] K --> L["π€ Response"] F -->|Error!| M["π¨ Exception Filter"] M --> K
π You Did It!
Now you understand ASP.NET Filters! Remember:
| Filter Type | When It Runs | Think Of It As |
|---|---|---|
| Resource | First & Last | Castle gate |
| Action | Before & After action | Referee |
| Exception | When errors happen | Safety net |
| Result | Before & After result | Gift wrapper |
π‘ Pro Tip: Filters keep your controller code clean. Instead of repeating the same checks in every action, create a filter once and use it everywhere!
Next up: Try building your own filter in the Interactive Lab! π
