Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
Кроме использования делегатов в методах Run/Use/Map мы можем создавать свои компоненты middleware в виде отдельных классов,
которые затем добавляются в конвейер с помощью метода UseMiddleware()
. Например, напишем свой примитивный компонент.
Для этого добавим в новый проект новый класс TokenMiddleware:
using Microsoft.AspNetCore.Http; using System.Threading.Tasks; public class TokenMiddleware { private readonly RequestDelegate _next; public TokenMiddleware(RequestDelegate next) { this._next = next; } public async Task InvokeAsync(HttpContext context) { var token = context.Request.Query["token"]; if (token!="12345678") { context.Response.StatusCode = 403; await context.Response.WriteAsync("Token is invalid"); } else { await _next.Invoke(context); } } }
Класс middleware должен иметь конструктор, который принимает параметр типа RequestDelegate. Через этот параметр можно получить ссылку на тот делегат запроса, который стоит следующим в конвейере обработки запроса.
Также в классе должен быть определен метод, который должен называться либо Invoke, либо InvokeAsync. Причем этот метод должен возвращать объект Task и принимать в качестве параметра контекст запроса - объект HttpContext. Данный метод собственно и будет обрабатывать запрос.
Суть действия класса заключается в том, что мы получаем из запроса параметр "token". Если полученный токен равен строке "12345678", то передаем запрос
дальше следующему компоненту, вызвав метод _next.Invoke()
. Иначе возвращаем пользователю сообщение об ошибке.
Для добавления компонента middleware, который представляет класс, в конвейер обработки запроса применяется метод UseMiddleware(). Так, изменим метод Configure класса Startup следующим образом:
public class Startup { public void Configure(IApplicationBuilder app) { app.UseMiddleware<TokenMiddleware>(); app.Run(async (context) => { await context.Response.WriteAsync("Hello World"); }); } }
С помощью метода UseMiddleware<T> в конструктор объекта TokenMiddleware будет внедряться объект
для параметра RequestDelegate next
. Поэтому явным образом передавать значение для этого параметра нам не нужно.
Запустим проект. И если мы не передадим через строку запроса параметр token или передадим для него значение, отличное от "12345678", то браузер отобразит ошибку:
Если же будет передан корректный токен, то метод app.UseToken()
передаст управление методу app.Run()
:
Также нередко для встраивания подобных компонентов middleware определяются специальные методы расширения. Так, добавим в проект новый класс, который назовем TokenExtensions:
using Microsoft.AspNetCore.Builder; public static class TokenExtensions { public static IApplicationBuilder UseToken(this IApplicationBuilder builder) { return builder.UseMiddleware<TokenMiddleware>(); } }
Здесь создается метод расширения для типа IApplicationBuilder. И этот метод встраивает компонент TokenMiddleware в конвейер обработки запроса. Как правило, подобные методы возвращают объект IApplicationBuilder.
Таким образом, у нас получится следующая структура проекта:
Теперь применим этот метод в методе Configure()
класса Startup:
public class Startup { public void Configure(IApplicationBuilder app) { app.UseToken(); app.Run(async (context) => { await context.Response.WriteAsync("Hello World"); }); } }
Изменим класс TokenMiddleware, чтобы он извне получал образец токена для сравнения:
using Microsoft.AspNetCore.Http; using System.Threading.Tasks; public class TokenMiddleware { private readonly RequestDelegate _next; string pattern; public TokenMiddleware(RequestDelegate next, string pattern) { this._next = next; this.pattern = pattern; } public async Task InvokeAsync(HttpContext context) { var token = context.Request.Query["token"]; if (token!=pattern) { context.Response.StatusCode = 403; await context.Response.WriteAsync("Token is invalid"); } else { await _next.Invoke(context); } } }
Образец токена, с которым идет сравнения, устанавливается через конструктор. Чтобы передать его в конструктор, изменим класс TokenExtensions:
using Microsoft.AspNetCore.Builder; public static class TokenExtensions { public static IApplicationBuilder UseToken(this IApplicationBuilder builder, string pattern) { return builder.UseMiddleware<TokenMiddleware>(pattern); } }
В метод builder.UseMiddleware
можно передать набор значений, которые передаются в конструктор компонента middleware.
Затем в методе Configure()
уже можно передать в метод расширения UseToken конкретное значение:
public void Configure(IApplicationBuilder app) { app.UseToken("555555"); app.Run(async (context) => { await context.Response.WriteAsync("Hello World"); }); }