Содержание
До этого момента при изучении ASP.NET Core мы использовали компоненты middleware в форме делегатов или, так называемые inline middleware. Такой подход позволяет довольно быстро встроить компонент middleware в конвейер запросов и продемонстрировать работу приложения. При этом, стоит учитывать, что далеко не всегда компонент middleware будет содержать минимум исходного кода и выполнять одно-два действия. В этом случае рекомендуется выносить логику middleware в отдельный класс с определенным описанием.
Требования к классу middleware
Чтобы ASP.NET Core мог использовать класс, как middleware, этот класс должен соответствовать следующим требованиям:
- Содержать открытый конструктор с параметром типа
RequestDelegate
. - Содержать открытый метод с именем
Invoke
илиInvokeAsync
, который должен:- вернуть
Task
; - принимать первым параметром объект типа
HttpContext
.
- вернуть
Вооружившись этими требованиями, напишем свой первый класс middleware в ASP.NET Core.
Класс middleware в ASP.NET Core
Создадим в приложении новый класс следующего содержания:
public class CharsetMiddleware { private RequestDelegate _next; //1. открытый конструктор с парамтером типа RequestDelegate public CharsetMiddleware(RequestDelegate next) { _next = next; } //2. открытый метод с именем InvokeAsync public async Task InvokeAsync(HttpContext context) { var charset = context.Request.Query["charset"]; context.Response.OnStarting( () => { if (string.IsNullOrWhiteSpace(charset)) context.Response.ContentType = "text/plain; charset=utf-8"; else context.Response.ContentType = $"text/plain; charset={charset}"; return Task.CompletedTask; }); await _next(context); } }
Здесь мы выполнили необходимые условия для создания класса middleware — создали открытый конструктор и метод InvokeAsync
. Этот компонент middleware будет проверять параметр запроса charset
и, если обнаружит его, то установит заданную в параметре кодировку текста или же укажет кодировку по умолчанию — utf-8.
Чтобы использовать этот middleware в нашем приложении мы можем воспользоваться методом UseMiddleware()
следующим образом:
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseMiddleware<CharsetMiddleware>(); //используем класс middlweare app.Run(async context => await context.Response.WriteAsync("Привет мир!")); app.Run(); }
Запустим приложение и посмотрим на результат:
кодировка по умолчанию — utf-8
меняем кодировку на KOI8-R:
Метод расширения для встраивания middleware
Несмотря на то, что для встраивания класса middleware в конвейер запросов мы можем пользоваться методом UseMiddleware
, всё же рекомендуется для каждого middleware создавать метод расширения для IApplicationBuilder
. Чтобы добавить метод расширения создадим новый класс следующего содержания:
public static class CharsetExtensions { public static IApplicationBuilder UseCharset(this IApplicationBuilder builder) { return builder.UseMiddleware<CharsetMiddleware>(); } }
теперь внедрение middleware в конвейер запросов можно осуществить следующим образом:
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseCharset(); //используем класс middlweare app.Run(async context => await context.Response.WriteAsync("Привет мир!")); app.Run(); }
Передача параметров в middleware
Изменим наш класс middleware следующим образом:
public class CharsetMiddleware { private RequestDelegate _next; private string _defaultCharset; //1. открытый конструктор с парамтером типа RequestDelegate public CharsetMiddleware(RequestDelegate next, string defaultCharset) { _next = next; _defaultCharset = defaultCharset; } //2. открытый метод с именем InvokeAsync public async Task InvokeAsync(HttpContext context) { var charset = context.Request.Query["charset"]; context.Response.OnStarting( () => { if (string.IsNullOrWhiteSpace(charset)) context.Response.ContentType = $"text/plain; charset={_defaultCharset}";//используем кодировку указанную в параметре else context.Response.ContentType = $"text/plain; charset={charset}"; return Task.CompletedTask; }); await _next(context); } }
Здесь мы, в качестве второго параметра, передаем в конструктор класса значение кодировки по умолчанию и используем её, если в запросе не задан параметр charset. Соответственно, необходимо изменить и метод расширения для IApplicationBuilder
public static class CharsetExtensions { public static IApplicationBuilder UseCharset(this IApplicationBuilder builder, string defaultCharset) { return builder.UseMiddleware<CharsetMiddleware>(defaultCharset); } }
Здесь мы в метод UseMiddleware()
передаем параметры из конструктора класса. Теперь встраивание middleware в конвейер будет выглядеть следующим образом:
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseCharset("utf-8"); //используем класс middlweare с параметром app.Run(async context => await context.Response.WriteAsync("Привет мир!")); app.Run(); }
Итого
Сегодня мы научились создавать middleware в виде классов и внедрять эти компоненты в конвейер запросов ASP.NET Core с использованием методов расширения. Класс middleware должен обладать рядом условий, в частности, иметь открытый метод InvokeAsync
.