Skip to content

Latest commit

 

History

History
202 lines (151 loc) · 8.1 KB

File metadata and controls

202 lines (151 loc) · 8.1 KB

Minimal API Endpoint Filters in ASP.NET Core (.NET 10)

Reusable request validation without controllersIEndpointFilter lets you intercept, validate, and short-circuit Minimal API requests in one clean, testable class.

.NET ASP.NET Core License: MIT Visit CodingDroplets YouTube Patreon Buy Me a Coffee GitHub


🚀 Support the Channel — Join on Patreon

If this sample saved you time, consider joining our Patreon community. You'll get exclusive .NET tutorials, premium code samples, and early access to new content — all for the price of a coffee.

👉 Join CodingDroplets on Patreon

Prefer a one-time tip? Buy us a coffee ☕


🎯 What You'll Learn

  • How to implement IEndpointFilter for reusable Minimal API validation
  • How to short-circuit a request and return early (e.g., 400 Bad Request) before the handler runs
  • How to chain multiple filters on a single endpoint
  • How to keep Program.cs clean by extracting cross-cutting concerns into filter classes
  • How to test endpoint filters with Swagger/OpenAPI

🗺️ Architecture Overview

Incoming HTTP Request
        │
        ▼
┌──────────────────────────────────────────────────────┐
│               Minimal API Pipeline                   │
│                                                      │
│  ┌────────────────────────────────────────────────┐  │
│  │   Filter 1: ProductValidationFilter            │  │
│  │   → Validate request body                     │  │
│  │   → Invalid? Return 400 immediately            │  │
│  │   → Valid?   Call next()                       │  │
│  └──────────────────┬─────────────────────────────┘  │
│                     │                                │
│  ┌──────────────────▼─────────────────────────────┐  │
│  │   Filter 2: (optional additional filters)      │  │
│  └──────────────────┬─────────────────────────────┘  │
│                     │                                │
│  ┌──────────────────▼─────────────────────────────┐  │
│  │   Endpoint Handler (the actual business logic) │  │
│  └────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────┘
        │
        ▼
   200 OK  /  400 Bad Request

📋 Filter Execution Flow

Stage Action Result
Pre-handler Filter inspects request Valid → continue; Invalid → short-circuit
Handler Business logic executes Returns response
Post-handler Filter can inspect/modify response Optional enrichment

📁 Project Structure

dotnet-minimal-api-endpoint-filters/
├── dotnet-minimal-api-endpoint-filters.sln
└── DotnetMinimalApiEndpointFilters.Api/
    ├── Filters/
    │   └── ProductValidationFilter.cs   # IEndpointFilter implementation
    ├── Models/
    │   └── Product.cs                   # Request model
    ├── Program.cs                       # Endpoint registration + filter wiring
    └── Properties/
        └── launchSettings.json

🛠️ Prerequisites

  • .NET 10 SDK
  • Any IDE: Visual Studio 2022+, VS Code, or JetBrains Rider

⚡ Quick Start

# Clone the repo
git clone https://github.com/codingdroplets/dotnet-minimal-api-endpoint-filters.git
cd dotnet-minimal-api-endpoint-filters

# Build and run
dotnet restore
dotnet run --project DotnetMinimalApiEndpointFilters.Api

# Open Swagger UI → http://localhost:{port}/swagger

🔧 How It Works

Step 1 — Implement IEndpointFilter

public class ProductValidationFilter : IEndpointFilter
{
    public async ValueTask<object?> InvokeAsync(
        EndpointFilterInvocationContext context,
        EndpointFilterDelegate next)
    {
        // Extract the request argument
        var product = context.GetArgument<Product>(0);

        // Validate — short-circuit if invalid
        if (string.IsNullOrWhiteSpace(product.Name))
            return Results.BadRequest("Product name is required.");

        if (product.Price <= 0)
            return Results.BadRequest("Price must be greater than zero.");

        // Valid — pass through to the handler
        return await next(context);
    }
}

Step 2 — Wire the Filter to an Endpoint

app.MapPost("/api/products", (Product product) =>
{
    // Only reached if the filter passes validation
    return Results.Created($"/api/products/{product.Id}", product);
})
.AddEndpointFilter<ProductValidationFilter>();

Step 3 — Chain Multiple Filters (Optional)

app.MapPost("/api/products", Handler)
   .AddEndpointFilter<ProductValidationFilter>()   // runs first
   .AddEndpointFilter<LoggingFilter>();             // runs second

🤔 IEndpointFilter vs Action Filter vs Middleware

IEndpointFilter Action Filter Middleware
Scope Single endpoint or group Controller/action Entire pipeline
Works with Minimal APIs
Works with Controllers
Access to endpoint metadata
Short-circuit support
Best for Minimal API validation MVC cross-cutting Global concerns

📚 References


📄 License

This project is licensed under the MIT License.


🔗 Connect with CodingDroplets

Platform Link
🌐 Website https://codingdroplets.com/
📺 YouTube https://www.youtube.com/@CodingDroplets
🎁 Patreon https://www.patreon.com/CodingDroplets
☕ Buy Me a Coffee https://buymeacoffee.com/codingdroplets
💻 GitHub http://github.com/codingdroplets/

Want more samples like this? Support us on Patreon or buy us a coffee ☕ — every bit helps keep the content coming!