Содержание
В предыдущей части мы рассмотрели метод 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()
может объединяться с основной.