Досрочное завершение и ветвление
Используйте MapWhen, UseWhen и завершающее промежуточное ПО, чтобы создавать ветви или завершать конвейер в зависимости от условий запроса.
«Досрочное завершение и ветвление» — бесплатный урок C# Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Ветвление и досрочное завершение
Не каждый запрос должен проходить через весь конвейер промежуточного ПО. ASP.NET Core предоставляет средства для ветвления, то есть перенаправления отдельных групп запросов в разные конвейеры, и для досрочного завершения, то есть остановки обработки с немедленным возвратом ответа.
Map: постоянная ветвь по пути
Map создаёт постоянную ветвь: запросы с подходящим префиксом переходят в эту ветвь и NEVER возвращаются в основной конвейер.
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: ветвление по условию
MapWhen создаёт ветвь на основе любого условия: заголовков, параметров запроса или пользовательской логики. Как и при использовании Map, ветвь является постоянной и не возвращается в основной конвейер.
// 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: условная ветвь с возвратом
UseWhen похож на MapWhen, но после завершения ветвь снова объединяется с основным конвейером. Это позволяет условно добавлять промежуточное ПО без создания отдельной ветви.
// 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();Досрочное завершение без вызова следующего компонента
Любой компонент промежуточного ПО может досрочно завершить конвейер, записав ответ и не вызвав next. На этом конвейер останавливается, а ответ возвращается клиенту.
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() в .NET 8
В .NET 8 MapShortCircuit и расширение ShortCircuit() для конечных точек предоставляют декларативный и высокооптимизированный путь досрочного завершения.
// 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;
}));Завершающее промежуточное ПО и маршрутизация конечных точек
До .NET 3 метод app.Run() был единственным способом завершить конвейер. Теперь предпочтительна маршрутизация конечных точек (MapGet, MapControllers): она участвует в авторизации, ограничении частоты запросов и обработке метаданных.
// 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");Особенности сопоставления путей
Map("/api") сопоставляется с /api и /api/anything. Сопоставленная часть пути удаляется из Request.Path внутри ветви и помещается в 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);
});Сочетание шаблонов ветвления
В реальных приложениях Map, UseWhen и досрочное завершение объединяются для создания многоуровневых конвейеров: для общедоступных маршрутов используется лёгкая обработка, для маршрутов программного интерфейса — аутентификация, а для административных маршрутов — дополнительные проверки.
// 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");
});Практический пример: промежуточное ПО для A/B-тестирования
Промежуточное ПО для A/B-тестирования направляет запросы к разным обработчикам на основе файла cookie или заголовка, не изменяя код конечных точек.
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();
});Быстрая проверка
В чём ключевая разница между MapWhen и UseWhen?
Повторение: досрочное завершение и ветвление
Основные выводы:
Map: постоянная ветвь на основе пути без возврата в основной конвейерMapWhen: постоянная ветвь на основе условияUseWhen: условная ветвь, которая снова объединяется с основным конвейером- Досрочное завершение: не вызывайте
next, запишите ответ и верните управление ShortCircuit()(.NET 8): декларативные и оптимизированные конечные точки, завершающие обработку- Сочетайте ветвление для создания многоуровневых конвейеров: общедоступные маршруты / маршруты программного интерфейса / административные маршруты
Изучай C# с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 93
- Уроки
- 346
Часто задаваемые вопросы
Урок «Досрочное завершение и ветвление» бесплатный?
Да — полный текст урока «Досрочное завершение и ветвление» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Досрочное завершение и ветвление»?
Используйте MapWhen, UseWhen и завершающее промежуточное ПО, чтобы создавать ветви или завершать конвейер в зависимости от условий запроса. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Досрочное завершение и ветвление»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Обзор конвейера ASP.NET Core
- Написание собственного промежуточного ПО
- Досрочное завершение и ветвление
- Порядок промежуточного ПО и встроенные компоненты