0Pricing
C# Academy · Lezione

Panoramica della pipeline di ASP.NET Core

Comprenda come le richieste attraversano la pipeline dei middleware e HttpContext e come vengono costruite le risposte.

Panoramica della pipeline di ASP.NET Core è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C# Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C# Academy include 4 lezioni in totale.

La pipeline delle richieste

Ogni richiesta HTTP in ASP.NET Core attraversa una pipeline di middleware. Ogni componente middleware può esaminare, modificare, interrompere o inoltrare la richiesta al componente successivo. Comprendere questa pipeline è fondamentale per creare app ASP.NET Core.

HttpContext: l'involucro della richiesta

HttpContext contiene tutte le informazioni relative a richiesta e risposta: intestazioni, cookie, corpo, attestazioni dell'utente, informazioni sulla connessione e token di annullamento. Tutti i middleware operano su di esso.

app.Use(async (context, next) =>
{
    // Read request info
    var method  = context.Request.Method;
    var path    = context.Request.Path;
    var headers = context.Request.Headers;
    var user    = context.User.Identity?.Name;

    // Write to response
    context.Response.Headers.Append("X-Processed-By", "MyMiddleware");

    await next(context); // forward to next middleware
});

Ordine di registrazione dei middleware

I middleware vengono eseguiti nell'ordine in cui sono registrati. La risposta viene riavvolta nell'ordine inverso, come in uno stack. L'ordine è fondamentale: l'autenticazione deve essere eseguita prima dell'autorizzazione; il routing prima della corrispondenza con gli endpoint.

// Typical order for an ASP.NET Core app:
app.UseExceptionHandler("/error"); // outermost — catches everything
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors("policy");
app.UseAuthentication();  // must be before Authorization
app.UseAuthorization();
app.UseRateLimiter();
app.UseOutputCache();
// MapHub, MapControllers, MapGet etc.
app.Run();

Use, Run e Map

Tre metodi aggiungono middleware: Use, che chiama il successivo; Run, terminale, che non chiama mai il successivo; e Map, che crea diramazioni in base al percorso.

// Use: passes to next
app.Use(async (ctx, next) =>
{
    Console.WriteLine("Before");
    await next(ctx);
    Console.WriteLine("After");
});

// Run: terminal — no next
app.Run(async ctx =>
    await ctx.Response.WriteAsync("Terminal"));

// Map: branch on path prefix
app.Map("/api", apiApp =>
    apiApp.Run(async ctx =>
        await ctx.Response.WriteAsync("API branch")));

Corpi delle richieste e delle risposte

I corpi delle richieste e delle risposte sono flussi. Il corpo della richiesta può essere letto una sola volta: abiliti il buffering del corpo della richiesta se deve essere letto più volte, ad esempio in più middleware.

app.Use(async (ctx, next) =>
{
    // Enable buffering so body can be read multiple times
    ctx.Request.EnableBuffering();

    using var reader = new StreamReader(
        ctx.Request.Body,
        leaveOpen: true);
    var body = await reader.ReadToEndAsync();
    ctx.Request.Body.Position = 0; // rewind for next middleware

    Console.WriteLine($"Body: {body}");
    await next(ctx);
});

Interruzione anticipata della pipeline

Un middleware può interrompere anticipatamente la pipeline scrivendo la risposta e NON chiamando next. È utile per i controlli di autenticazione, i controlli di integrità o le pagine di manutenzione.

app.Use(async (ctx, next) =>
{
    if (ctx.Request.Path == "/maintenance")
    {
        ctx.Response.StatusCode = 503;
        await ctx.Response.WriteAsync("Service under maintenance");
        return; // short-circuit — next is NOT called
    }
    await next(ctx);
});

L'interfaccia IMiddleware

Per un middleware basato su classi che necessita dell'inserimento delle dipendenze, implementi IMiddleware. Registri l'implementazione nel contenitore DI e utilizzi app.UseMiddleware<T>().

public class RequestTimingMiddleware : IMiddleware
{
    private readonly ILogger<RequestTimingMiddleware> _logger;
    public RequestTimingMiddleware(ILogger<RequestTimingMiddleware> l) => _logger = l;

    public async Task InvokeAsync(HttpContext ctx, RequestDelegate next)
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();
        await next(ctx);
        _logger.LogInformation("{Method} {Path}: {Ms}ms",
            ctx.Request.Method, ctx.Request.Path, sw.ElapsedMilliseconds);
    }
}

// Register:
builder.Services.AddTransient<RequestTimingMiddleware>();
app.UseMiddleware<RequestTimingMiddleware>();

Classi di middleware convenzionali

In alternativa, crei una classe con un metodo InvokeAsync(HttpContext, RequestDelegate). Il framework inserisce le dipendenze, incluso il delegato successivo, tramite il costruttore.

public class ApiKeyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly string _key;

    // RequestDelegate injected by framework
    public ApiKeyMiddleware(RequestDelegate next, IConfiguration cfg)
    {
        _next = next;
        _key = cfg["ApiKey"] ?? "";
    }

    public async Task InvokeAsync(HttpContext ctx)
    {
        if (ctx.Request.Headers["X-Api-Key"] != _key)
        {
            ctx.Response.StatusCode = 401;
            return;
        }
        await _next(ctx);
    }
}

Modificare le risposte dopo next

Il codice dopo await next(ctx) viene eseguito dopo l'inizio della scrittura della risposta. È possibile aggiungere intestazioni alla risposta prima di next, ma non è possibile modificare il codice di stato o il corpo dopo questo punto.

app.Use(async (ctx, next) =>
{
    // Before: add response headers (safe)
    ctx.Response.OnStarting(() =>
    {
        ctx.Response.Headers.Append("X-Request-Id",
            Guid.NewGuid().ToString("N"));
        return Task.CompletedTask;
    });

    await next(ctx);

    // After: response may already be sent
    // SAFE: logging, metrics
    // UNSAFE: changing status code or writing body
    Console.WriteLine($"Response status: {ctx.Response.StatusCode}");
});

Caso reale: middleware per l'ID di correlazione

Un middleware per l'ID di correlazione, usato in produzione, aggiunge un ID di traccia a ogni richiesta per la traccia distribuita e la registrazione dei log.

public class CorrelationIdMiddleware
{
    private readonly RequestDelegate _next;
    private const string Header = "X-Correlation-Id";

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

    public async Task InvokeAsync(HttpContext ctx)
    {
        var correlationId = ctx.Request.Headers[Header].FirstOrDefault()
            ?? Guid.NewGuid().ToString("N");

        ctx.Items["CorrelationId"] = correlationId;

        ctx.Response.OnStarting(() =>
        {
            ctx.Response.Headers.Append(Header, correlationId);
            return Task.CompletedTask;
        });

        using (Serilog.Context.LogContext.PushProperty("CorrelationId", correlationId))
            await _next(ctx);
    }
}

Verifica rapida

Qual è la differenza tra app.Use() e app.Run() quando si aggiunge un middleware?

Riepilogo: panoramica della pipeline ASP.NET Core

Punti chiave:

  • I middleware vengono eseguiti nell'ordine di registrazione; le risposte vengono riavvolte nell'ordine inverso
  • Use → chiama il successivo; Run → terminale; Map → diramazione basata sul percorso
  • HttpContext contiene richiesta, risposta, utente e token di annullamento
  • Abiliti il buffering per leggere più volte il corpo della richiesta
  • L'interfaccia IMiddleware consente middleware basati su classi compatibili con DI
  • Aggiunga le intestazioni della risposta tramite OnStarting(); non modifichi lo stato dopo next

Domande Frequenti

La lezione «Panoramica della pipeline di ASP.NET Core» è gratuita?

Sì — il testo completo di «Panoramica della pipeline di ASP.NET Core» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C# Academy, passa a CoddyKit PRO. Il corso C# Academy include 4 lezioni in totale.

Cosa imparerò in «Panoramica della pipeline di ASP.NET Core»?

Comprenda come le richieste attraversano la pipeline dei middleware e HttpContext e come vengono costruite le risposte. Eserciti C# Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C# Academy?

Non è richiesta alcuna esperienza precedente. C# Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Panoramica della pipeline di ASP.NET Core»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C# Academy?

Sì. Ogni lezione C# Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Panoramica della pipeline di ASP.NET Core
  2. Scrittura di middleware personalizzati
  3. Interruzione anticipata e ramificazione
  4. Ordine dei middleware e middleware integrati
← Torna a C# Academy