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łączeniaMapWhen: trwałe rozgałęzienie na podstawie predykatuUseWhen: 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
- Przegląd potoku ASP.NET Core
- Pisanie niestandardowego middleware
- Skracanie i rozgałęzianie potoku
- Kolejność middleware i wbudowane middleware