C# Academy · Oppitunti

ASP.NET Coren putken yleiskatsaus

Ymmärtäkää, miten pyynnöt kulkevat middleware-putken ja HttpContextin läpi sekä miten vastaukset rakennetaan.

Oppitunti 1/412 vaihetta

ASP.NET Coren putken yleiskatsaus on ilmainen C# Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C# Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C# Academy-kurssilla on yhteensä 4 oppituntia.

Pyyntöputki

Jokainen ASP.NET Core -kehyksen HTTP-pyyntö kulkee middleware-putken läpi. Jokainen middleware-komponentti voi tarkastella tai muokata pyyntöä, katkaista käsittelyn tai välittää pyynnön seuraavalle komponentille. Putken ymmärtäminen on olennaista ASP.NET Core -sovellusten rakentamisessa.

HttpContext: pyynnön tietosisältö

HttpContext sisältää kaikki pyyntöön ja vastaukseen liittyvät tiedot: otsakkeet, evästeet, rungon, käyttäjän väitteet, yhteystiedot ja peruutustunnisteen. Kaikki middleware-komponentit toimivat sen kautta.

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
});

Middleware-komponenttien rekisteröintijärjestys

Middleware-komponentit suoritetaan siinä järjestyksessä, jossa ne rekisteröidään. Vastaus kulkee takaisin päinvastaisessa järjestyksessä, aivan kuten pinossa. Järjestys on ratkaiseva: autentikoinnin on tapahduttava ennen valtuutusta ja reitityksen ennen päätepisteen täsmäytystä.

// 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 ja Map

Middleware-komponentteja voidaan lisätä kolmella menetelmällä: Use kutsuu seuraavaa komponenttia, Run on päättävä eikä koskaan kutsu seuraavaa, ja Map haarauttaa käsittelyn polun perusteella.

// 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")));

Pyyntö- ja vastausrungot

Pyyntöjen ja vastausten rungot ovat tietovirtoja. Pyynnön rungon voi lukea vain kerran — ottakaa käyttöön pyynnön rungon puskurointi, jos se on luettava useita kertoja, esimerkiksi useassa middleware-komponentissa.

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);
});

Putken käsittelyn katkaiseminen

Middleware-komponentti voi katkaista putken kirjoittamalla vastauksen eikä kutsumalla next-komponenttia. Tämä on hyödyllistä esimerkiksi autentikoinnin tarkistuksissa, terveystarkistuksissa ja huoltosivuilla.

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);
});

IMiddleware-rajapinta

Jos luokkapohjainen middleware tarvitsee riippuvuuksien injektointia, toteuttakaa IMiddleware. Rekisteröikää toteutus DI-säilöön ja käyttäkää app.UseMiddleware<T>()-kutsua.

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>();

Konventiopohjaiset middleware-luokat

Vaihtoehtoisesti voitte luoda luokan, jossa on InvokeAsync(HttpContext, RequestDelegate)-menetelmä. Kehys injektoi riippuvuudet, myös seuraavan delegaatin, konstruktorin kautta.

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);
    }
}

Vastausten muokkaaminen next-kutsun jälkeen

await next(ctx)-kutsun jälkeinen koodi suoritetaan sen jälkeen, kun vastauksen kirjoittaminen on alkanut. Vastausotsakkeita voi lisätä ennen next-kutsua, mutta tilakoodia tai runkoa ei voi enää muuttaa sen jälkeen.

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}");
});

Käytännössä: korrelaatiotunnusmiddleware

Tuotantokäyttöön tarkoitettu korrelaatiotunnusmiddleware lisää jäljitystunnisteen jokaiseen pyyntöön hajautettua jäljitystä ja lokitusta varten.

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);
    }
}

Pikatarkistus

Mitä eroa on app.Use()- ja app.Run()-kutsuilla middleware-komponentteja lisättäessä?

Kertaus: ASP.NET Core -putken yleiskatsaus

Keskeiset opit:

  • Middleware-komponentit suoritetaan rekisteröintijärjestyksessä ja vastaukset purkautuvat päinvastaisessa järjestyksessä
  • Use → kutsuu seuraavaa; Run → päättävä; Map → polkuun perustuva haara
  • HttpContext sisältää pyynnön, vastauksen, käyttäjän ja peruutustunnisteen
  • Ottakaa puskurointi käyttöön, jotta pyynnön runko voidaan lukea useita kertoja
  • IMiddleware-rajapinta mahdollistaa DI-ystävällisen luokkapohjaisen middlewaren
  • Lisätkää vastausotsakkeet OnStarting()-kutsulla; älkää muuttako tilakoodia next-kutsun jälkeen
Aloita maksutta

Opi C# tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
93
Oppitunnit
346

Usein kysytyt kysymykset

Onko oppitunti ”ASP.NET Coren putken yleiskatsaus” ilmainen?

Kyllä – oppitunnin ”ASP.NET Coren putken yleiskatsaus” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C# Academy-kurssin, päivitä CoddyKit PROhon. C# Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”ASP.NET Coren putken yleiskatsaus”?

Ymmärtäkää, miten pyynnöt kulkevat middleware-putken ja HttpContextin läpi sekä miten vastaukset rakennetaan. Harjoittelet C# Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C# Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C# Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”ASP.NET Coren putken yleiskatsaus”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C# Academy-oppitunnilla?

Kyllä. Jokainen C# Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. ASP.NET Coren putken yleiskatsaus
  2. Mukautetun middlewaren kirjoittaminen
  3. Putken oikosulkeminen ja haaroittaminen
  4. Middlewaren järjestys ja sisäänrakennettu middleware
← Takaisin: C# Academy