0Pricing
C# Academy · Lekcja

Skracanie i rozgałęzianie potoku

Używaj MapWhen, UseWhen i końcowego middleware do rozgałęziania lub kończenia potoku na podstawie warunków żądania.

Skracanie i rozgałęzianie potoku to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.

Rozgałęzianie i zatrzymywanie potoku

Nie każde żądanie powinno przechodzić przez cały potok middleware. ASP.NET Core udostępnia narzędzia do rozgałęziania (kierowania podzbiorów żądań do różnych potoków) i zatrzymywania potoku (przerwania przetwarzania i natychmiastowego zwrócenia odpowiedzi).

Map: trwałe rozgałęzienie według ścieżki

Map tworzy trwałą gałąź — żądania pasujące do prefiksu trafiają do gałęzi i NIGDY nie wracają do głównego potoku.

app.Map("/api", apiApp =>
{
    apiApp.UseAuthentication();
    apiApp.UseAuthorization();
    apiApp.Run(async ctx =>
        await ctx.Response.WriteAsync("API branch"));
});

// Requests to /api/... enter the branch above.
// Requests to /public/... skip the branch entirely.
app.Run(async ctx =>
    await ctx.Response.WriteAsync("Main pipeline"));

MapWhen: rozgałęzienie na podstawie predykatu

MapWhen tworzy rozgałęzienie na podstawie dowolnego warunku, takiego jak nagłówki, parametry zapytania lub własna logika. Podobnie jak w przypadku Map, gałąź jest trwała i nie łączy się ponownie z głównym potokiem.

// Branch when a specific header is present
app.MapWhen(
    ctx => ctx.Request.Headers.ContainsKey("X-Internal"),
    internalApp =>
    {
        internalApp.UseMiddleware<InternalApiMiddleware>();
        internalApp.Run(async ctx =>
            await ctx.Response.WriteAsync("Internal route"));
    });

// Branch on query parameter
app.MapWhen(
    ctx => ctx.Request.Query.ContainsKey("legacy"),
    legacyApp => legacyApp.UseMiddleware<LegacyHandlerMiddleware>());

UseWhen: warunkowe rozgałęzienie z ponownym połączeniem

UseWhen działa podobnie jak MapWhen, ale po zakończeniu obsługi gałąź ponownie łączy się z głównym potokiem. Dzięki temu można warunkowo dodawać middleware bez tworzenia osobnej gałęzi potoku.

// Log only for authenticated API calls; public routes not logged
app.UseWhen(
    ctx => ctx.Request.Path.StartsWithSegments("/api")
           && ctx.User.Identity?.IsAuthenticated == true,
    loggedApp =>
    {
        loggedApp.UseMiddleware<AuditMiddleware>();
    });

// All requests continue here after the branch
app.UseRouting();
app.MapControllers();

Zatrzymywanie potoku przez niewywołanie next

Dowolne middleware może zatrzymać potok, zapisując odpowiedź i nie wywołując next. W tym miejscu potok się zatrzymuje, a odpowiedź jest zwracana klientowi.

app.Use(async (ctx, next) =>
{
    // IP allowlist check
    var ip = ctx.Connection.RemoteIpAddress?.ToString();
    var allowed = new[] { "127.0.0.1", "::1", "10.0.0.0/8" };

    if (!IsAllowed(ip, allowed))
    {
        ctx.Response.StatusCode = 403;
        await ctx.Response.WriteAsJsonAsync(
            new { error = "Access denied from this IP" });
        return; // short-circuit
    }

    await next(ctx); // proceed
});

ShortCircuit() w .NET 8

W .NET 8 elementy MapShortCircuit oraz rozszerzenie ShortCircuit() dla endpointów udostępniają deklaratywną, wysoce zoptymalizowaną ścieżkę zatrzymywania potoku.

// Reject known bad paths immediately — skip entire pipeline
app.MapShortCircuit(404, "robots.txt", "favicon.ico");

// Or on a specific endpoint:
app.MapGet("/health", () => "OK")
   .ShortCircuit(); // skips auth, rate limiting, etc.

// 'Run' middleware also short-circuits:
app.Map("/old-api", old =>
    old.Run(ctx =>
    {
        ctx.Response.StatusCode = 301;
        ctx.Response.Headers.Location = "/api/v2";
        return Task.CompletedTask;
    }));

Terminalne middleware a routing endpointów

Przed wersją .NET 3 metoda app.Run() była jedyną opcją terminalną. Obecnie preferowany jest routing endpointów (MapGet, MapControllers) — uczestniczy on w autoryzacji, ograniczaniu liczby żądań i obsłudze metadanych.

// OLD: terminal middleware
app.Run(async ctx => {
    if (ctx.Request.Path == "/ping")
        await ctx.Response.WriteAsync("pong");
});

// PREFERRED: endpoint routing
app.MapGet("/ping", () => "pong")
   .WithTags("Health")
   .AllowAnonymous()
   .RequireRateLimiting("basic");

Niuanse dopasowywania ścieżek

Map("/api") pasuje do /api oraz /api/anything. Dopasowana część ścieżki jest usuwana z Request.Path wewnątrz gałęzi i umieszczana w Request.PathBase.

app.Map("/api", apiApp =>
{
    apiApp.Use(async (ctx, next) =>
    {
        // Path in branch: /users/42 (prefix removed)
        Console.WriteLine(ctx.Request.Path);     // /users/42
        Console.WriteLine(ctx.Request.PathBase); // /api
        await next(ctx);
    });
    apiApp.MapGet("/users/{id}", (int id) => id);
});

Łączenie wzorców rozgałęziania

Rzeczywiste aplikacje łączą Map, UseWhen i zatrzymywanie potoku, aby tworzyć warstwowe potoki: trasy publiczne są lekkie, trasy API mają uwierzytelnianie, a trasy administracyjne dodatkowe kontrole.

// Public area — no auth
app.Map("/public", pub =>
{
    pub.MapGet("/health", () => "OK");
    pub.MapGet("/docs",   () => "Documentation");
});

// API area — full auth + rate limiting
app.Map("/api", api =>
{
    api.UseAuthentication();
    api.UseAuthorization();
    api.UseRateLimiter();
    api.MapControllers();
});

// Admin area — require admin role
app.Map("/admin", admin =>
{
    admin.UseAuthentication();
    admin.UseAuthorization();
    admin.MapControllers().RequireAuthorization("AdminPolicy");
});

Praktyczny przykład: middleware testów A/B

Middleware testów A/B kieruje żądania do różnych handlerów na podstawie pliku cookie lub nagłówka, bez modyfikowania kodu endpointów.

app.UseWhen(
    ctx => ctx.Request.Cookies.TryGetValue("ab-group", out var g) && g == "B",
    betaApp =>
    {
        betaApp.Use(async (ctx, next) =>
        {
            ctx.Items["IsGroupB"] = true;
            await next(ctx);
        });
    });

// Endpoint reads the flag:
app.MapGet("/products", (HttpContext ctx, ProductService svc) =>
{
    bool isB = ctx.Items.ContainsKey("IsGroupB");
    return isB ? svc.GetNewLayoutAsync() : svc.GetOldLayoutAsync();
});

Szybki test

Jaka jest kluczowa różnica między MapWhen a UseWhen?

Podsumowanie: zatrzymywanie i rozgałęzianie potoku

Najważniejsze informacje:

  • Map: trwałe rozgałęzienie na podstawie ścieżki, bez ponownego połączenia
  • MapWhen: trwałe rozgałęzienie na podstawie predykatu
  • UseWhen: warunkowe rozgałęzienie, które ponownie łączy się z głównym potokiem
  • Zatrzymanie potoku: nie wywołuj next, zapisz odpowiedź i zakończ obsługę
  • ShortCircuit() (.NET 8): deklaratywne, zoptymalizowane endpointy terminalne
  • Łącz rozgałęzienia, aby tworzyć warstwowe potoki: publiczne / API / administracyjne

Często zadawane pytania

Czy lekcja „Skracanie i rozgałęzianie potoku” jest bezpłatna?

Tak — pełny tekst „Skracanie i rozgałęzianie potoku” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Skracanie i rozgałęzianie potoku”?

Używaj MapWhen, UseWhen i końcowego middleware do rozgałęziania lub kończenia potoku na podstawie warunków żądania. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C# Academy?

Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Skracanie i rozgałęzianie potoku”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?

Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Przegląd potoku ASP.NET Core
  2. Pisanie niestandardowego middleware
  3. Skracanie i rozgałęzianie potoku
  4. Kolejność middleware i wbudowane middleware
← Powrót do C# Academy