Содержание
В предыдущей части мы рассмотрели метод Map(), который также как и методы Run() и Use() используется для встраивания middleware в конвейер запросов ASP.NET и, при этом, создает ветвление конвейера. Сегодня рассмотрим ещё два метода ASP.NET Core для встраивания middleware и ветвления конвейера запросов — это методы MapWhen() и UseWhen().
Метод MapWhen
Метод MapWhen реализован как метод расширения IApplicationBuilder и имеет следующую сигнатуру:
IApplicationBuilder MapWhen(this IApplicationBuilder app, Func<HttpContext, bool> predicate, Action<IApplicationBuilder> configuration)
здесь
predicate— это делегат, который представляет собой некоторое условие. В качестве входного параметра принимает контекст запроса (HttpContext), а в качестве результата возвращаетtrue, если условие оказывается истинно.configuration— действие в котором производится работа с объектом типаIApplicationBuilder, то есть, по сути, настраивается новая ветка конвейера запросов ASP.NET
Рассмотрим работу этого метода на примере:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapWhen(
context=>context.Request.Path.StartsWithSegments("/page"),//условие - путь начинается с /page
//работаем с IApplicationBuilder
appBuilder =>
{
//встраиваем первый middleware
appBuilder.Use(async (context, next) =>
{
//выводим текущее время
await context.Response.WriteAsync($"Время: {DateTime.Now} \r\n");
await next.Invoke();
});
//страиваем второй middleware
appBuilder.Run(async context =>
{
await context.Response.WriteAsync($"Путь: {context.Request.Path}");
});
}
);
app.Run(async context => await context.Response.WriteAsync("Index page"));
app.Run();
}
}
В качестве условия для создания новой ветки мы указали:
context=>context.Request.Path.StartsWithSegments("/page")
то есть, если запрашивается любая страница, путь которой начинается с /path, то условие будет истинным. Далее, мы создаем новую ветку конвейера запросов, в которую страиваем два компонента middleware:
appBuilder =>
{
//встраиваем первый middleware
appBuilder.Use(async (context, next) =>
{
//выводим текущее время
await context.Response.WriteAsync($"Время: {DateTime.Now} \r\n");
await next.Invoke();
});
//страиваем второй middleware
appBuilder.Run(async context =>
{
await context.Response.WriteAsync($"Путь: {context.Request.Path}");
});
}
первый компонент выведет на страницу текущее время, а второй — путь. В запущенном приложении это может выглядеть следующим образом:
Для удобства, мы можем вынести проверку условия и действия по созданию ветки в отдельные методы. Например, так:
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapWhen(IsPage, CreateBranch);
app.Run(async context => await context.Response.WriteAsync("Index page"));
app.Run();
//проверка условия
static bool IsPage(HttpContext context)
{
return context.Request.Path.StartsWithSegments("/page");
}
void CreateBranch(IApplicationBuilder appBuilder)
{
//встраиваем первый middleware
appBuilder.Use(async (context, next) =>
{
//выводим текущее время
await context.Response.WriteAsync($"Время: {DateTime.Now} \r\n");
await next.Invoke();
});
//страиваем второй middleware
appBuilder.Run(async context =>
{
await context.Response.WriteAsync($"Путь: {context.Request.Path}");
});
}
}
Метод UseWhen
Метод UseWhen() во многом схож с MapWhen() и также принимает в качестве параметра делегат в котором проверяется некоторое условие. Основным отличием является то, что новая ветвь объединяется с основной веткой, если новая ветвь не содержит терминального middleware. Например, перепишем наш код следующим образом:
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
//новая ветка теперь будет объединяться с основной
app.UseWhen(IsPage, CreateBranch);
app.Run(async context => await context.Response.WriteAsync("Index page"));
app.Run();
static bool IsPage(HttpContext context)
{
return context.Request.Path.StartsWithSegments("/page");
}
void CreateBranch(IApplicationBuilder appBuilder)
{
appBuilder.Use(async (context, next) =>
{
await context.Response.WriteAsync($"Время: {DateTime.Now} \r\n");
await next.Invoke();
});
//убрали терминальный middleware
appBuilder.Use(async (context, next) =>
{
await context.Response.WriteAsync($"Путь: {context.Request.Path}\r\n");
await next.Invoke();
});
}
}
}
Теперь запустим приложение и получим следующий результат:
Так как в UseWhen() мы не использовали терминальный middleware, то новая ветка конвейера была объединена с основной.
Дополнительно стоит также напомнить, что, как и в случае с методом Map(), новые ветки конвейера создаются один раз.
Итого
Сегодня мы рассмотрели ещё два метода, позволяющих осуществить ветвление конвейера запросов — MapWhen() и UseWhen(). Оба этих метода работают практически идентично — на основании заданного условия создают новую ветку конвейера. При этом, ветка, создаваемая с использованием UseWhen() может объединяться с основной.

