Содержание
До этого момента при изучении 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.

