Skrive egendefinert middleware
Opprett inline-middleware med Use/Run/Map og klassebasert middleware med InvokeAsync for gjenbrukbare komponenter.
Skrive egendefinert middleware er en gratis leksjon i C# Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i C# Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i C# Academy inneholder totalt 4 leksjoner.
Hvorfor egendefinert middleware?
Egendefinert middleware håndterer tverrgående funksjonalitet som gjelder mange forespørsler: logging, tidsmåling, feilhåndtering, autentisering, komprimering og caching. Når logikken skrives én gang, kjøres den automatisk for hver forespørsel som samsvarer.
Inline-middleware med Use
Den raskeste måten å legge til middleware på er å sende en delegat til app.Use(). Dette passer godt for prototyper eller virkelig enkel logikk.
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");
});Klassebasert middleware (konvensjon)
En konvensjonell middleware-klasse har en konstruktør som mottar RequestDelegate, og en offentlig InvokeAsync-metode. Ytterligere konstruktørparametere kan injiseres fra DI.
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 for DI-Scoped-avhengigheter
Hvis middleware trenger scoped-tjenester, for eksempel DbContext, implementeres IMiddleware. Registrer det som Scoped, så løser rammeverket det på nytt for hver forespørsel.
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 med Options
Send konfigurasjon til middleware via et options-objekt i konstruktøren. Registrer options med DI-beholderen, eller send dem direkte når middleware registreres.
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 for unntakshåndtering
Et egendefinert middleware for unntakshåndtering fanger opp alle uhåndterte unntak og returnerer strukturerte feilsvar.
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 for forespørselslogging
Et strukturert middleware for logging av forespørsler og svar registrerer metode, sti, statuskode og medgått tid for hver forespørsel.
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);
}
}Betinget middleware med UseWhen
UseWhen forgrener pipelinen betinget basert på et predikat, uten å dele den permanent. Forgreningen kobles tilbake til hovedpipelinen etterpå.
// 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 for caching av responser
Det innebygde middleware-et for caching av responser lagrer komplette responser i minnet. Konfigurer cache-policyer per endepunkt ved hjelp av headere eller attributter.
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"));I praksis: Middleware for vedlikeholdsmodus
Et middleware for vedlikeholdsmodus leser et flagg fra konfigurasjonen, med støtte for hot reload via IOptionsMonitor, og avviser forespørsler som ikke er helsesjekker under vedlikehold.
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);
}
}Kunnskapssjekk
Hvorfor bør IMiddleware implementeres i stedet for den konvensjonsbaserte tilnærmingen når det er behov for en scoped-tjeneste, for eksempel DbContext?
Oppsummering: Skrive egendefinert middleware
Viktigste punkter:
- Inline (Use-delegat): raskt for korte uttrykk; klassebasert: gjenbrukbart og testbart
- Konvensjonell klasse: konstruktøren mottar RequestDelegate; InvokeAsync(HttpContext)
- IMiddleware: DI-oppløsning per forespørsel – nødvendig for Scoped-avhengigheter
- UseWhen: betinget forgrening som kobles tilbake til hovedpipelinen
- Skriv middleware for unntakshåndtering først, altså ytterst, for å fange opp alle feil
- Opprett extension methods (UseXxx) for ryddig og oppdagbar registrering
Lær deg C# med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 93
- Leksjoner
- 346
Ofte stilte spørsmål
Er leksjonen «Skrive egendefinert middleware» gratis?
Ja – hele teksten i «Skrive egendefinert middleware» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av C# Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i C# Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Skrive egendefinert middleware»?
Opprett inline-middleware med Use/Run/Map og klassebasert middleware med InvokeAsync for gjenbrukbare komponenter. Du øver på C# Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med C# Academy?
Ingen tidligere erfaring er nødvendig. C# Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Skrive egendefinert middleware»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne C# Academy-leksjonen?
Ja. Alle C# Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Oversikt over ASP.NET Core-pipelinen
- Skrive egendefinert middleware
- Kortslutning og forgrening
- Rekkefølge og innebygd middleware