customization

Mcafee123's avatarfrom Mcafee123

Configure middleware extension hooks for affolterNET.Web.Bff. Use when adding custom middleware, extending the pipeline, or integrating third-party components.

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 8, 2026

When & Why to Use This Skill

This Claude skill enables developers to seamlessly extend the affolterNET.Web.Bff middleware pipeline by configuring custom extension hooks. It simplifies the integration of custom logic, third-party components, and request processing behaviors at critical stages of the web request lifecycle, specifically after routing and before endpoint execution, ensuring a highly customizable and robust Backend-for-Frontend architecture.

Use Cases

  • Multi-tenancy Implementation: Use the 'AfterRouting' hook to extract tenant IDs from headers or routes and inject them into the request context for downstream services.
  • Security and Audit Logging: Utilize the 'BeforeEndpoints' hook to capture authenticated user claims and log detailed access patterns for compliance and monitoring.
  • Performance Tracking: Integrate custom timing middleware to measure request duration and append performance metrics like 'X-Response-Time' to the response headers.
  • Request Context Enrichment: Add custom middleware to populate HttpContext.Items with shared data or services required by multiple API endpoints.
namecustomization
descriptionConfigure middleware extension hooks for affolterNET.Web.Bff. Use when adding custom middleware, extending the pipeline, or integrating third-party components.

Customization Hooks

Extend the BFF middleware pipeline with custom components.

For complete reference, see Library Guide.

Extension Points

The BFF provides two middleware hooks:

Hook Position Use Case
ConfigureAfterRoutingCustomMiddleware After routing Tenant resolution, request context
ConfigureBeforeEndpointsCustomMiddleware Before endpoints Audit logging, final validation

Quick Start

var options = builder.Services.AddBffServices(isDev, config, opts => {
    opts.ConfigureAfterRoutingCustomMiddleware = app => {
        app.UseMiddleware<TenantMiddleware>();
        app.UseMiddleware<RequestContextMiddleware>();
    };

    opts.ConfigureBeforeEndpointsCustomMiddleware = app => {
        app.UseMiddleware<AuditMiddleware>();
    };
});

Middleware Pipeline Position

1. Exception Handling
2. Security Headers
3. HTTPS Redirection
4. Static Files
5. Swagger
6. Routing
7. ══► ConfigureAfterRoutingCustomMiddleware ◄══
8. CORS
9. Antiforgery
10. Authentication & Authorization
11. Token Refresh
12. RPT Middleware
13. NoUnauthorizedRedirect
14. Antiforgery Token
15. ══► ConfigureBeforeEndpointsCustomMiddleware ◄══
16. API 404 Handling
17. Endpoint Mapping

Example: Tenant Middleware

public class TenantMiddleware
{
    private readonly RequestDelegate _next;

    public TenantMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // Extract tenant from route or header
        var tenantId = context.Request.RouteValues["tenant"]?.ToString()
            ?? context.Request.Headers["X-Tenant-Id"].FirstOrDefault();

        if (!string.IsNullOrEmpty(tenantId))
        {
            context.Items["TenantId"] = tenantId;
        }

        await _next(context);
    }
}

Example: Audit Middleware

public class AuditMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<AuditMiddleware> _logger;

    public AuditMiddleware(RequestDelegate next, ILogger<AuditMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var userId = context.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        var path = context.Request.Path;
        var method = context.Request.Method;

        _logger.LogInformation("User {UserId} accessing {Method} {Path}",
            userId, method, path);

        await _next(context);
    }
}

Example: Request Timing

public class TimingMiddleware
{
    private readonly RequestDelegate _next;

    public TimingMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext context)
    {
        var sw = Stopwatch.StartNew();

        context.Response.OnStarting(() => {
            sw.Stop();
            context.Response.Headers["X-Response-Time"] = $"{sw.ElapsedMilliseconds}ms";
            return Task.CompletedTask;
        });

        await _next(context);
    }
}

Accessing Services

public async Task InvokeAsync(HttpContext context, IMyService myService)
{
    // Services can be injected via InvokeAsync
    var result = await myService.DoSomethingAsync();
    await _next(context);
}

Troubleshooting

Middleware not executing

  • Verify hook is configured correctly
  • Check middleware order dependencies
  • Add logging to confirm registration

User claims not available

  • After-routing hook runs before authentication
  • Use before-endpoints hook for authenticated context