Introduction
ASP.NET Core Minimal APIs have become a popular way to build lightweight and high-performance APIs. However, as applications grow, developers often need to perform common tasks before or after an endpoint executes.
Examples include:
Request validation
Logging
Authentication checks
Performance monitoring
Response modification
Before .NET 7, developers typically used Middleware or custom logic inside endpoints. To simplify these scenarios, Microsoft introduced Endpoint Filters.
Endpoint Filters provide a clean way to run code before and after a Minimal API endpoint executes, making applications easier to maintain and extend.
In this article, you'll learn what Endpoint Filters are, how they work, and how to implement them in ASP.NET Core applications.
What Are Endpoint Filters?
Endpoint Filters allow developers to intercept requests before and after a Minimal API endpoint executes.
Think of them as a pipeline around an endpoint.
Request
↓
Endpoint Filter
↓
Endpoint
↓
Response
This makes it possible to add reusable logic without cluttering endpoint code.
Why Use Endpoint Filters?
Consider a simple endpoint:
app.MapPost("/products",
(Product product) =>
{
return Results.Ok(product);
});
Suppose you need validation for multiple endpoints.
Without Endpoint Filters:
Endpoint 1
Validation Logic
Endpoint 2
Validation Logic
Endpoint 3
Validation Logic
The same code gets repeated.
With Endpoint Filters:
Filter
↓
Reusable Validation
↓
All Endpoints
This improves maintainability.
How Endpoint Filters Work
An Endpoint Filter implements the IEndpointFilter interface.
Example:
public class LoggingFilter
: IEndpointFilter
{
public async ValueTask<object?>
InvokeAsync(
EndpointFilterInvocationContext context,
EndpointFilterDelegate next)
{
Console.WriteLine(
"Request Started");
var result =
await next(context);
Console.WriteLine(
"Request Completed");
return result;
}
}
The filter executes code before and after the endpoint.
Registering an Endpoint Filter
Attach the filter to an endpoint.
app.MapGet("/users",
() => Results.Ok("Users"))
.AddEndpointFilter<LoggingFilter>();
When the endpoint executes:
Request Started
↓
Endpoint Executes
↓
Request Completed
The filter automatically runs.
Using Endpoint Filters for Validation
A common use case is request validation.
Example:
public class ValidationFilter
: IEndpointFilter
{
public async ValueTask<object?>
InvokeAsync(
EndpointFilterInvocationContext context,
EndpointFilterDelegate next)
{
var product =
context.GetArgument<Product>(0);
if (string.IsNullOrWhiteSpace(
product.Name))
{
return Results.BadRequest(
"Product Name Required");
}
return await next(context);
}
}
Register:
app.MapPost("/products",
(Product product) =>
{
return Results.Ok(product);
})
.AddEndpointFilter<ValidationFilter>();
The endpoint remains clean while validation logic is centralized.
Inline Endpoint Filters
For simple scenarios, you can define filters directly.
Example:
app.MapGet("/hello",
() => "Hello World")
.AddEndpointFilter(
async (context, next) =>
{
Console.WriteLine("Before");
var result =
await next(context);
Console.WriteLine("After");
return result;
});
This is useful for small, endpoint-specific logic.
Real-World Example
Imagine an e-commerce API.
Endpoints:
Create Product
Update Product
Delete Product
Each endpoint requires:
Logging
Validation
Request tracking
Instead of repeating logic:
Endpoint Filter
↓
Shared Functionality
↓
Multiple Endpoints
This reduces code duplication significantly.
Endpoint Filters vs Middleware
Many developers wonder when to use Middleware versus Endpoint Filters.
Middleware
Works globally.
Request
↓
Middleware
↓
All Endpoints
Best for:
Authentication
Exception handling
Global logging
Endpoint Filters
Work at endpoint level.
Request
↓
Endpoint Filter
↓
Specific Endpoint
Best for:
Use the right tool for the right requirement.
Advantages of Endpoint Filters
Endpoint Filters provide several benefits:
These advantages make Minimal APIs easier to manage.
Best Practices
When using Endpoint Filters:
Keep filters focused on a single responsibility.
Use filters for endpoint-specific logic.
Avoid complex business logic inside filters.
Use Middleware for global concerns.
Reuse filters across related endpoints.
Keep endpoint methods clean and readable.
Following these practices improves application architecture.
Conclusion
Endpoint Filters are a powerful addition to ASP.NET Core Minimal APIs. They allow developers to execute logic before and after endpoint execution, making it easier to implement validation, logging, monitoring, and other cross-cutting concerns.
By moving reusable functionality into filters, applications become cleaner, more maintainable, and easier to scale. Whether you're building small APIs or enterprise applications, Endpoint Filters provide a flexible way to organize endpoint-specific behavior without cluttering business logic.