Asp.Net Core Filters
1. The Problem
Imagine an ASP.NET Core Web API with dozens of controllers and endpoints.
Several endpoints need to perform common work:
- Check whether the request is authorized.
- Validate incoming data.
- Log execution details.
- Handle certain exceptions.
- Run something before or after an action executes.
For example:
POST /api/orders GET /api/orders/123 PUT /api/orders/123 DELETE /api/orders/123
You could put the same logic inside every controller action. But that quickly becomes repetitive.
CreateOrder() +-- check something +-- log something +-- execute business logic +-- handle something UpdateOrder() +-- check something +-- log something +-- execute business logic +-- handle something DeleteOrder() +-- check something +-- log something +-- execute business logic +-- handle something
Now imagine changing that common behavior. You have to find every action that contains it.
The controller starts becoming responsible for things that aren't really part of the business operation.
2. What's Actually Going Wrong?
The problem is cross-cutting concerns are getting mixed into controller actions.
A controller action should primarily deal with the request and the application operation it represents.
CreateOrder()
|
v
Create the order
But if the action also contains:
CreateOrder() +-- authorization check +-- logging +-- validation +-- exception handling +-- business logic +-- response creation
the action becomes harder to understand and maintain.
ASP.NET Core provides Filters to move certain types of cross-cutting behavior outside the action itself.
3. The Concept
An ASP.NET Core Filter allows you to run code at specific points around MVC controller/action execution.
Conceptually:
HTTP Request | v ASP.NET Core Pipeline | v Controller Filters (Before Action) | v Controller Action | v Controller Filters (After Action) | v HTTP Response
The filter gets an opportunity to participate in processing without putting the same logic directly inside every controller action.
4. What Types of Filters Are Available?
ASP.NET Core provides several filter types, each operating at a different stage.
HTTP Request
|
v
Authorization Filters
|
v
Resource Filters
|
v
Action Filters
|
v
Controller Action
|
v
Exception Filters
|
v
Result Filters
|
v
HTTP Response
The exact MVC pipeline has additional details, but this gives you the useful mental model.
Authorization Filters
These run early and are concerned with whether the request is allowed to proceed.
Request | v Authorization Filter | +-- Not allowed --> Stop | +-- Allowed -----> Continue
ASP.NET Core's authorization system, including [Authorize], is the normal place to handle authorization requirements.
The important point is:
Don't put authorization checks manually inside every controller action when ASP.NET Core's authorization mechanisms already provide the appropriate pipeline behavior.
Resource Filters
Resource filters run around much of the MVC processing and can execute before model binding.
They can be useful when you need to control behavior at a point that is earlier than action execution.
Think of them as a broader boundary around MVC resource processing.
Action Filters
Action filters run immediately around controller action execution.
Before Action
|
v
Controller Action
|
v
After Action
They are useful for cross-cutting behavior such as:
- Logging action execution
- Measuring execution time
- Applying common action-level behavior
- Performing reusable checks that genuinely belong at the action boundary
The important benefit is that the controller action can stay focused on its actual operation.
Exception Filters
Exception filters allow you to participate in handling exceptions thrown during MVC action execution.
Controller Action
|
| exception
v
Exception Filter
|
v
HTTP Response
However, exception filters are not the universal exception-handling mechanism for an entire ASP.NET Core application.
For application-wide exception handling, ASP.NET Core's exception-handling middleware is often the more appropriate architectural choice.
That distinction matters.
Result Filters
Result filters run around the execution of an MVC action result.
Controller Action
|
v
Action Result
|
v
Result Filter
|
v
HTTP Response
They are useful when the concern specifically relates to processing the action result.
5. How Do You Use Filters?
The important architectural question isn't:
“How do I create a filter?”
It is:
“Is this behavior really an MVC action concern?”
If yes, a filter can be a good fit.
Logging every controller action
|
v
Action Filter
Instead of:
CreateOrder() +-- logging +-- business logic +-- response UpdateOrder() +-- logging +-- business logic +-- response
You can keep the controller focused:
Action Filter
|
v
CreateOrder()
|
v
Business Logic
Filters can be applied at different scopes, such as:
- Globally
- To a controller
- To a specific action
This allows you to decide how broadly the behavior should apply.
6. Filters vs Middleware
This is one of the most important distinctions for an ASP.NET Core engineer.
Both can run code around requests, but they operate at different levels.
Middleware
Middleware operates in the ASP.NET Core request pipeline.
HTTP Request
|
v
Middleware
|
v
Routing
|
v
MVC
|
v
Controller
Middleware is therefore appropriate for concerns that apply broadly across the application. Examples:
- Global exception handling
- Request/response logging
- Authentication-related pipeline behavior
- Correlation IDs
- General HTTP concerns
Filters
Filters operate within the MVC/controller pipeline.
HTTP Request
|
v
ASP.NET Core
|
v
MVC
|
v
Filters
|
v
Controller Action
They are appropriate when the concern is specifically related to MVC action execution.
The Mental Model
ASP.NET Core
|
v
Middleware
|
v
MVC
|
v
Filters
|
v
Controller Action
So don't automatically create a filter just because you want reusable request logic. First ask:
Does this belong to the overall HTTP pipeline, or specifically to MVC/action execution?
7. Filters vs Business Logic
Filters should not become a dumping ground for business rules.
For example, suppose you have:
OrderService
+-- calculate price
+-- apply discount
+-- check inventory
+-- create order
These are business/application responsibilities. They shouldn't be moved into an Action Filter simply because the logic is reusable.
A better separation is:
Controller
|
v
Filter
| (cross-cutting MVC concern)
v
Controller Action
|
v
Application / Domain Logic
Filter: “Something that needs to happen around the action.”
Service: “Something that the application needs to do.”
That distinction keeps the architecture clean.
8. When Should You Use It?
Use ASP.NET Core Filters when:
- The concern is closely related to MVC/controller execution.
- The same behavior applies to multiple actions.
- You need behavior before or after an action.
- You need action-level exception/result processing.
- You want to avoid duplicating cross-cutting MVC behavior.
Typical examples include:
Action Filters
+-- Action-level logging
+-- Execution timing
+-- Common MVC behavior
Authorization Filters
+-- Authorization-related processing
Exception Filters
+-- MVC-specific exception handling
Result Filters
+-- Action-result processing
9. What Happens If You Use Filters for Everything?
You can end up with a controller where the actual behavior is difficult to discover.
Request | v Filter A | v Filter B | v Filter C | v Middleware | v Another Filter | v Controller
A developer looking at the controller may not realize that several important things happen before or after the action.
Filters should therefore be used deliberately. A useful rule is:
Use a filter when the behavior naturally belongs around MVC action execution, not simply because the behavior is reusable.
10. Visualize It in Everyday Terms
Think about a restaurant. A customer enters the restaurant and eventually reaches the waiter who takes the order.
There are different checks and activities around that interaction.
Customer | v Entry Check | v Table Preparation | v Waiter Takes Order | v Order Processing | v Bill / Result
Mapping this to ASP.NET Core:
- Entry Check → Authorization Filter
- Table Preparation → Resource Filter
- Before taking order → Action Filter
- Taking the order → Controller Action
- Handling an issue → Exception Filter
- Preparing the bill → Result Filter
The key idea is:
Filters let you attach reusable behavior around a specific stage of MVC processing without putting that behavior inside every controller action.
11. What Should You Remember?
Don't think:
“Filters are a way to avoid writing duplicate code.”
Think:
“Filters are hooks into the ASP.NET Core MVC execution pipeline.”
Remember the distinction:
Middleware
| (application-wide HTTP pipeline)
v
MVC
| (MVC-specific pipeline)
v
Filters
|
v
Controller Action
And remember:
- Authorization Filter → Is the request allowed to proceed?
- Resource Filter → Behavior around MVC resource processing.
- Action Filter → Behavior around controller action execution.
- Exception Filter → MVC-specific exception handling.
- Result Filter → Behavior around action-result execution.
12. .NET + Azure Context
In a typical ASP.NET Core Web API hosted in Azure, the architecture might look like:
Azure | v ASP.NET Core API | v Middleware | v MVC | v Filters (Authorization / Resource / Action) | v Controller Action | v Application Service | v EF Core / Azure SQL
Relevant .NET building blocks include:
- ASP.NET Core MVC
IAuthorizationFilterIResourceFilterIActionFilterIExceptionFilterIResultFilter- Attribute-based filters such as
[Authorize] - ASP.NET Core middleware
- Dependency Injection for filter dependencies
In Azure, the API might be hosted on:
- Azure App Service
- Azure Container Apps
- Azure Kubernetes Service
The hosting platform doesn't change what a filter is. The important architectural point is:
ASP.NET Core Filters are an MVC-level extension point. Use them for concerns that belong around controller/action execution, while keeping application and business logic in the appropriate services.