Веб-версияОткрыть в Telegram

ПостДень 2787. #ЗаметкиНаПолях #Middleware

17 сентября 2026
.
.NET Разработчик
День 2787. #ЗаметкиНаПолях #Middleware Что Такое Промежуточное ПО и Его Подводные Камни. Начало В этой серии постов разберём, что представляет собой промежуточное ПО, как написать собственный компонент и с какими неожиданными проблемами могут столкнуться разработчики. Создание промежуточного ПО Промежуточное ПО добавляется в файле Program.cs с помощью метода app.Use(): app.Use(async (ctx, next) => { Console.WriteLine($"Запрос: {ctx.Request.Path}"); await next(ctx); Console.WriteLine($"Ответ: {ctx.Response.StatusCode}"); }); Промежуточное ПО выполняется при каждом HTTP-запросе. Каждый запрос проходит через него на входе, а ответ — на выходе. Вызов next() играет ключевую роль: он обеспечивает переход к следующему компоненту в конвейере обработки. Если забыть его добавить, выполнение конвейера остановится, и все последующие компоненты промежуточного ПО не будут запущены. Недостаток подхода с app.Use() в использовании лямбда-выражения, что затрудняет тестирование. Более удачное решение — вынести логику в отдельный класс: public class RequestLoggingMiddleware { private readonly RequestDelegate _next; public RequestLoggingMiddleware(RequestDelegate next) => _next = next; public async Task InvokeAsync(HttpContext ctx) { Console.WriteLine($"Запрос: {ctx.Request.Path}"); await _next(ctx); Console.WriteLine($"Ответ: {ctx.Response.StatusCode}"); } } Не забывайте внедрять next в конструктор, чтобы использовать его для вызова следующего компонента промежуточного ПО в конвейере. Затем зарегистрируйте этот компонент в файле Program.cs; вызов app.Use(…) можно удалить: app.UseMiddleware<RequestLoggingMiddleware>(); Если не зарегистрировать класс, промежуточное ПО никогда не выполнится. Порядок регистрации промежуточного ПО в Program.cs имеет значение. Если мы зарегистрируем RequestLoggingMiddleware первым, этот компонент первым обработает запрос, а ответ – последним: app.UseMiddleware<RequestLoggingMiddleware>(); app.UseSwaggerUI(opts => { opts.SwaggerEndpoint("/openapi/v1.json", "Api"); }); app.MapOpenApi(); var group = app.MapGroup("/api"); group.MapGet("test", () => TypedResults.Content("Это тест", "text/plain");); Если забыть вызвать next() public class RequestLoggingMiddleware { … public async Task InvokeAsync(HttpContext ctx) { Console.WriteLine($"Запрос: {ctx.Request.Path}"); //await _next(ctx); Console.WriteLine($"Response: {ctx.Response.StatusCode}"); } } При запуске приложения страница не отобразится. При вызове конечной точки API через Postman вместо строки «Это тест» возвращается пустой ответ со статусом 200. Это происходит из-за того, что RequestLoggingMiddleware зарегистрирован первым. Если он прерывает цепочку и не вызывает next(), то ни один из последующих компонентов промежуточного ПО, включая эндпоинты API и Swagger, не выполнится. Это полезно в некоторых случаях, когда вы хотите прервать обработку в зависимости от некоторого условия. Однако чаще всего необходимо вызывать next(). Промежуточное ПО — это синглтон, а InvokeAsync имеет время жизни scoped Зарегистрируйте scoped-сервис в Program.cs: builder.Services.AddScoped<IMyScopedService, MyScopedService>(); Теперь внедрите его в RequestLoggingMiddleware. public class RequestLoggingMiddleware { //… public RequestLoggingMiddleware( RequestDelegate next, IMyScopedService mySvc) { //… } //… } При запуске приложения возникает ошибка: Cannot resolve scoped service 'IMyScopedService' from root provider (Не удаётся разрешить scoped-сервис IMyScopedService из корневого провайдера). Это происходит потому, что метод UseMiddleware создаёт экземпляр класса промежуточного ПО один раз, используя корневой провайдер сервисов приложения, и повторно использует этот же экземпляр для каждого запроса. Сервис с областью видимости scoped нельзя получить напрямую из корневого провайдера. Решение в том, чтобы убрать IMyScopedService из конструктора и внедрять его непосредственно в метод InvokeAsync: public class RequestLoggingMiddleware { //… public async Task InvokeAsync( HttpContext context, IMyScopedService mySvc) { //… } } Метод InvokeAsync выполняется заново для каждого запроса, поэтому ASP.NET Core каждый раз разрешает IMyScopedService из области видимости текущего запроса. Окончание следует… Источник: https://www.roundthecode.com/dotnet-tutorials/what-is-middleware-aspnet-core-and-gotchas
17 · 1.4K ·

Рядом в ленте

..NET РазработчикОпрос..NET РазработчикДень 2786. #AI Пусть Copilot Поспорит с Вами Как разработчик или архитектор, вы ежедневно принимаете множество проектных решений. Вы выбираете Redis для кэширов
это сообщение
..NET РазработчикДень 2788. #ЗаметкиНаПолях #Middleware Что Такое Промежуточное ПО и Его Подводные Камни. Окончание Начало Изменение ответа после начала его отправки В данном сл..NET РазработчикДень 2789. #Оффтоп #AI Важно ли По-прежнему Качество Кода? Автор оригинала: Марк Симан Пока мы используем LLM как инструмент для генерации кода, за который в ит
..NET Разработчик.NET Разработчик@NetDeveloperDiary · канал · Технологии
6 750подписчиков1 347средний охват поста
Лента площадки Открыть в Telegram

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Чего мы не делаем · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем