Самый простой способ добавления middleware в конвейер обработки запроса в ASP.NET Core представляет метод Run(), который определен как метод расширения для интерфейса IApplicationBuilder (соответствено его поддерживает и класс WebApplication):
IApplicationBuilder.Run(RequestDelegate handler)
Метод Run
добавляет терминальный компонент - такой компонент, который завершает обработку запроса. Поэтому соответствено он не вызывает никакие другие компоненты и обработку запроса дальше - следующим в конвейере
компонентам не передает. Поэтому данный метод следует вызывать в самом конце построения конвейера обработки запроса.
До него же могут быть помещены другие методы, которые добавляют компоненты middleware.
В качестве параметра метод Run принимает делегат RequestDelegate. Этот делегат имеет следующее определение:
public delegate Task RequestDelegate(HttpContext context);
Он принимает в качестве параметра контекст запроса HttpContext и возвращает объект Task.
Используем этот метод для определения простейшего компонента:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Run(async (context) => await context.Response.WriteAsync("Hello METANIT.COM")); app.Run();
Здесь для делегата RequestDelegate передается лямбда-выражение, параметр которого - HttpContext можно использовать для отправки ответа.
В частности, метод context.Response.WriteAsync()
позволяет отправить клиенту некоторый ответ - в данном случае отправляется простая строка.
После запуска проекта будет запущено приложение откроется браузер, который выполнит запрос к приложению и получит обратно строку "Hello METANIT.COM".
Здесь следует сделать пару замечаний. Прежде всего, не стоит путать метод Run(), который определен в классе WebApplication и который запускает приложение, и метод расширения Run(), который встраивает компонент middleware. Это два разных метода, которые выполняют разные задачи. И, как видно из кода выше, вызываются оба этих метода.
Второй момент - метод Run(), который запускает приложение, вызывается после добавления компонента middleware. И мы НЕ можем написать так:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Run(); // приложение запущено // в этой строке уже нет смысла app.Run(async (context) => await context.Response.WriteAsync("Hello METANIT.COM"));
При необходимости естественно мы можем вынести код middleware в отдельный метод:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Run(HandleRequst); app.Run(); async Task HandleRequst(HttpContext context) { await context.Response.WriteAsync("Hello METANIT.COM 2"); }
Компоненты middleware создаются один раз и существуют в течение всего жизненного цикла приложения. То есть для последующей обработки запросов используются одни и те же компоненты. Например, определим в файле Program.cs следующий код:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); int x = 2; app.Run(async (context) => { x = x * 2; // 2 * 2 = 4 await context.Response.WriteAsync($"Result: {x}"); }); app.Run();
При запуске приложения мы естественно ожидаем, что браузер выведет число 4 в качестве результата:
Однако при последующих запросах мы увидим, что результат переменной х не равен 4.
Также стоит отметить, что браузер Google Chrome может посылать два запроса - один собственно к приложению, а другой - к файлу иконки favicon.ico, поэтому в Google Chrome результат может отличаться не 2 раза, а гораздо больше.