0Pricing
C# Academy · Lektion

Benutzerdefinierte Middleware schreiben

Erstellen Sie Inline-Middleware mit Use/Run/Map und klassenbasierte Middleware mit InvokeAsync für wiederverwendbare Komponenten.

Benutzerdefinierte Middleware schreiben ist eine kostenlose C# Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C# Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum benutzerdefinierte Middleware?

Benutzerdefinierte Middleware übernimmt Querschnittsbelange, die für viele Anfragen gelten: Logging, Zeitmessung, Fehlerbehandlung, Authentifizierung, Komprimierung und Caching. Wenn Sie die Logik einmal schreiben, wird sie automatisch für jede passende Anfrage ausgeführt.

Inline-Middleware mit Use

Die schnellste Möglichkeit, Middleware hinzuzufügen: Übergeben Sie einen Delegaten an app.Use(). Das eignet sich für Prototypen oder wirklich einfache Logik.

app.Use(async (context, next) =>
{
    var start = DateTimeOffset.UtcNow;

    await next(context);

    var elapsed = DateTimeOffset.UtcNow - start;
    context.Response.Headers.Append(
        "X-Elapsed", elapsed.TotalMilliseconds.ToString("F0") + "ms");
});

Klassenbasierte Middleware nach Konvention

Eine konventionelle Middleware-Klasse verfügt über einen Konstruktor, der RequestDelegate entgegennimmt, und eine öffentliche Methode InvokeAsync. Zusätzliche Konstruktorparameter können aus DI injiziert werden.

public class SecurityHeadersMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context)
    {
        var headers = context.Response.Headers;
        headers.Append("X-Content-Type-Options", "nosniff");
        headers.Append("X-Frame-Options", "DENY");
        headers.Append("X-XSS-Protection", "1; mode=block");
        headers.Append("Referrer-Policy", "strict-origin-when-cross-origin");

        await _next(context);
    }
}

// Extension method for clean registration:
public static class SecurityHeadersExtensions
{
    public static IApplicationBuilder UseSecurityHeaders(
        this IApplicationBuilder app) =>
        app.UseMiddleware<SecurityHeadersMiddleware>();
}

IMiddleware für Scoped-Abhängigkeiten aus DI

Wenn Ihre Middleware Scoped-Dienste wie DbContext benötigt, implementieren Sie IMiddleware. Registrieren Sie sie als Scoped, damit das Framework sie für jede Anfrage neu auflöst.

public class AuditMiddleware : IMiddleware
{
    private readonly AuditDbContext _db;
    private readonly IHttpContextAccessor _http;

    public AuditMiddleware(AuditDbContext db, IHttpContextAccessor http)
    {
        _db = db;
        _http = http;
    }

    public async Task InvokeAsync(HttpContext ctx, RequestDelegate next)
    {
        await next(ctx);

        if (ctx.Request.Method != "GET")
        {
            _db.AuditLogs.Add(new AuditLog
            {
                User   = ctx.User.Identity?.Name,
                Path   = ctx.Request.Path,
                Status = ctx.Response.StatusCode,
                At     = DateTime.UtcNow
            });
            await _db.SaveChangesAsync();
        }
    }
}

builder.Services.AddScoped<AuditMiddleware>();
app.UseMiddleware<AuditMiddleware>();

Middleware mit Optionen

Übergeben Sie die Konfiguration über ein Optionsobjekt im Konstruktor an die Middleware. Registrieren Sie die Optionen im DI-Container oder übergeben Sie sie inline, wenn Sie die Middleware registrieren.

public class ThrottleOptions
{
    public int MaxRequestsPerSecond { get; set; } = 100;
    public string[] ExcludedPaths { get; set; } = Array.Empty<string>();
}

public class ThrottleMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ThrottleOptions _options;

    public ThrottleMiddleware(RequestDelegate next, ThrottleOptions options)
    {
        _next   = next;
        _options = options;
    }
    // ...
}

// Registration with options:
app.UseMiddleware<ThrottleMiddleware>(new ThrottleOptions
{
    MaxRequestsPerSecond = 50
});

Middleware zur Ausnahmebehandlung

Eine benutzerdefinierte Middleware zur Ausnahmebehandlung fängt alle unbehandelten Ausnahmen ab und gibt strukturierte Fehlerantworten zurück.

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

    public GlobalExceptionMiddleware(RequestDelegate next, ILogger<GlobalExceptionMiddleware> l)
    {
        _next = next;
        _logger = l;
    }

    public async Task InvokeAsync(HttpContext ctx)
    {
        try { await _next(ctx); }
        catch (NotFoundException ex)
        {
            ctx.Response.StatusCode = 404;
            await ctx.Response.WriteAsJsonAsync(new { error = ex.Message });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Unhandled exception");
            ctx.Response.StatusCode = 500;
            await ctx.Response.WriteAsJsonAsync(new { error = "Internal server error" });
        }
    }
}

Middleware für Anforderungsprotokollierung

Eine strukturierte Middleware zur Protokollierung von Anfragen und Antworten erfasst für jede Anfrage Methode, Pfad, Statuscode und verstrichene Zeit.

public class RequestLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestLoggingMiddleware> _log;

    public RequestLoggingMiddleware(RequestDelegate n, ILogger<RequestLoggingMiddleware> l)
    { _next = n; _log = l; }

    public async Task InvokeAsync(HttpContext ctx)
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();
        await _next(ctx);
        sw.Stop();

        _log.LogInformation(
            "{Method} {Path} -> {Status} in {Ms}ms",
            ctx.Request.Method,
            ctx.Request.Path,
            ctx.Response.StatusCode,
            sw.ElapsedMilliseconds);
    }
}

Bedingte Middleware mit UseWhen

UseWhen verzweigt die Pipeline anhand eines Prädikats bedingt, ohne sie dauerhaft aufzuteilen. Nach Abschluss kehrt der Zweig in die Hauptpipeline zurück.

// Apply authentication middleware only to /api/* routes
app.UseWhen(
    ctx => ctx.Request.Path.StartsWithSegments("/api"),
    apiApp =>
    {
        apiApp.UseAuthentication();
        apiApp.UseAuthorization();
    });

// Public routes (/public/*) bypass authentication
app.MapGet("/public/health", () => "OK");
app.MapGet("/api/data", [Authorize] async (DataService s) => await s.GetAsync());

Middleware für Response-Caching

Die integrierte Middleware für Response-Caching speichert vollständige Antworten im Arbeitsspeicher. Konfigurieren Sie Cache-Richtlinien pro Endpunkt mithilfe von Headern oder Attributen.

builder.Services.AddResponseCaching();

app.UseResponseCaching();

app.MapGet("/products", async (AppDbContext db) =>
{
    var products = await db.Products.AsNoTracking().ToListAsync();
    return Results.Ok(products);
})
.CacheOutput(p => p.Expire(TimeSpan.FromMinutes(2)).Tag("products"));

Praxisbeispiel: Middleware für den Wartungsmodus

Eine Middleware für den Wartungsmodus liest ein Flag aus der Konfiguration, unterstützt über IOptionsMonitor auch das Nachladen, und weist während der Wartung Anfragen ab, die keine Health Checks sind.

public class MaintenanceMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IOptionsMonitor<MaintenanceOptions> _options;

    public MaintenanceMiddleware(RequestDelegate next,
        IOptionsMonitor<MaintenanceOptions> opts)
    { _next = next; _options = opts; }

    public async Task InvokeAsync(HttpContext ctx)
    {
        if (_options.CurrentValue.IsEnabled
            && !ctx.Request.Path.StartsWithSegments("/health"))
        {
            ctx.Response.StatusCode = 503;
            ctx.Response.Headers.Append("Retry-After", "300");
            await ctx.Response.WriteAsJsonAsync(
                new { message = "Service under maintenance" });
            return;
        }
        await _next(ctx);
    }
}

Kurztest

Warum sollten Sie IMiddleware statt des konventionsbasierten Ansatzes implementieren, wenn Sie einen Scoped-Dienst wie DbContext benötigen?

Zusammenfassung: Benutzerdefinierte Middleware schreiben

Wichtige Erkenntnisse:

  • Inline-Middleware (Use-Delegat): schnell, für Einzeiler; klassenbasierte Middleware: wiederverwendbar und testbar
  • Konventionelle Klasse: Der Konstruktor erhält RequestDelegate; InvokeAsync(HttpContext)
  • IMiddleware: DI-Auflösung pro Anfrage – erforderlich für Scoped-Abhängigkeiten
  • UseWhen: bedingte Verzweigung, die wieder in die Hauptpipeline eintritt
  • Schreiben Sie die Middleware zur Ausnahmebehandlung zuerst, also äußersten, damit sie alle Fehler abfängt
  • Erstellen Sie Erweiterungsmethoden (UseXxx) für eine übersichtliche und leicht auffindbare Registrierung

Häufig gestellte Fragen

Ist die Lektion „Benutzerdefinierte Middleware schreiben“ kostenlos?

Ja — der vollständige Text von „Benutzerdefinierte Middleware schreiben“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C# Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Benutzerdefinierte Middleware schreiben“?

Erstellen Sie Inline-Middleware mit Use/Run/Map und klassenbasierte Middleware mit InvokeAsync für wiederverwendbare Komponenten. Du übst C# Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C# Academy zu starten?

Keine Vorkenntnisse erforderlich. C# Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Benutzerdefinierte Middleware schreiben“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C# Academy-Lektion Code schreiben und ausführen?

Ja. Jede C# Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Überblick über die ASP.NET-Core-Pipeline
  2. Benutzerdefinierte Middleware schreiben
  3. Kurzschließen und Verzweigen
  4. Reihenfolge und integrierte Middleware
← Zurück zu C# Academy