Сочетание конечных точек с другими middleware

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

Кроме конечных точек запрос в конвейере обработки могут обрабатывать и другие компоненты middleware. При этом надо учитывать общий процесс обработки запроса и вызова конечных точек.

Так, если приложение содержит конечные точки, то система маршрутизации на основе процессе URL matching или сопоставления адреса URL с шаблонами маршрута выбирает для обработки определенную конечную точку. Если в приложении есть такая конечная точка, которая соответствует запросу, то компонент middleware Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware устанавливает у объекта HttpContext конечную точку для будущей обработки запроса, которую можно получить с помощью метода HttpContext.GetEndpoint(). Кроме того, устанавливаются значения маршрута, которые можно получить через коллекцию HttpRequest.RouteValues

Однако конечная точка начинает обрабатывать запрос только после того, как все middleware в конвейере начнут обработку запроса. Например, возьмем следующий код приложения:

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Use(async (context, next) =>
{
    Console.WriteLine("First middleware starts");
    await next.Invoke();
    Console.WriteLine("First middleware ends");
});
app.Map("/", () =>
{
    Console.WriteLine("Index endpoint starts and ends");
    return "Index Page";
});
app.Use(async (context, next) =>
{
    Console.WriteLine("Second middleware starts");
    await next.Invoke();
    Console.WriteLine("Second middleware ends");
});
app.Map("/about", () =>
{
    Console.WriteLine("About endpoint starts and ends");
    return "About Page";
});
app.Run();

Здесь до и после первой конечной точки с помощью метода app.Use() в конвейер встроены два middleware. Для получения общей картины выполнения приложения процесс выполнения логгируется на консоль приложения.

Если мы запустим приложение, то при запросе по адресу "/" ожидаемо для обработки запроса будет выбрана первая конечная точка

Сочетание конечных точек endpoint и middleware в конвейере обработки запроса в ASP.NET Core и C#

Но теперь взглянем на консоль приложения:

Порядок выполнения конечных точек и middleware в конвейере обработки запроса в ASP.NET Core и C#

Мы видим, что конечная точка выполняется после того, как начнет выполняться компонент middleware, который в коде идет после добавления этой конечной точки.

При этом в компонентах middleware также можно обрабатывать запросы по определенным адресам:

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Use(async (context, next) =>
{
    if (context.Request.Path == "/date")
        await context.Response.WriteAsync($"Date: {DateTime.Now.ToShortDateString()}");
    else
        await next.Invoke();
});

app.Map("/", () => "Index Page");
app.Map("/about", () => "About Page");

app.Run();

Кроме того, middleware могут быть полезны для некоторого постдействия - выполнения некоторых действий, когда конечная точка уже выбрана. Или, наоборот, если ни одна из конечных точек не обработала запрос, и в middleware мы можем обработать эту ситуацию:

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Use(async(context, next) =>
{
    await next.Invoke();

    if (context.Response.StatusCode == 404)
        await context.Response.WriteAsync("Resource Not Found");
});
app.Map("/", () => "Index Page");
app.Map("/about", () => "About Page");
app.Run();

Однако если в конце конвейера располагается терминальный компонент, то он будет выполняться даже если конечная точка соответствует запрошенному пути:

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Map("/", () => "Index Page");
app.Map("/about", () => "About Page");

app.Run(async context =>
{
    context.Response.StatusCode = 404;
    await context.Response.WriteAsync("Resource not found");
});
app.Run();

В данном случае по результату программы мы видим, что даже при запросах по адресу "/" и "/about" будет выполняться middleware из метода app.Run:

Терминальный middleware и Map в ASP.NET Core и C#

Почему такое происходит? Опять же потому что, сначала выполняются все middleware в конвейере, и только потом выполняется конечная точка.

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