Метод Run и определение терминального middleware

Последнее обновление: 10.12.2021

Самый простой способ добавления 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".

Установка middleware в ASP.NET Core с помощью метода Run

Здесь следует сделать пару замечаний. Прежде всего, не стоит путать метод 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

Компоненты 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 в качестве результата:

Жизненный цикл middleware в ASP.NET Core и C#

Однако при последующих запросах мы увидим, что результат переменной х не равен 4.

Жизненный цикл приложения в ASP.NET Core и C#

Также стоит отметить, что браузер Google Chrome может посылать два запроса - один собственно к приложению, а другой - к файлу иконки favicon.ico, поэтому в Google Chrome результат может отличаться не 2 раза, а гораздо больше.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850