В ASP.NET Core 6 представлена упрощенная модель хостинга, которая позволяет нам создавать облегченные API с минимальными зависимостями. Минимальные API в ASP.NET Core 6 не используют контроллеры и не поддерживают ряд полезных функций ASP.NET. Одной из таких недостающих функций являются фильтры.
Однако с помощью ASP.NET Core 7 (теперь доступного в качестве кандидата на выпуск) мы можем воспользоваться преимуществами недавно представленного интерфейса IRouteHandlerFilter для включения фильтров в наши минимальные API. Эти фильтры можно использовать для изменения объектов запроса или ответа по желанию или для сокращения конвейера обработки запросов.
В этой статье обсуждается, как мы можем работать с фильтрами обработчиков маршрутов при создании минимальных приложений API в ASP.NET Core 7. Чтобы использовать примеры кода, представленные в этой статье, в вашей системе должна быть установлена предварительная версия Visual Studio 2022. Если у вас еще нет копии, вы можете скачать Visual Studio 2022 здесь.
Создайте минимальный проект веб-API ASP.NET Core 7 в Visual Studio 2022.
Прежде всего давайте создадим проект ASP.NET Core 7 в Visual Studio 2022 Preview. Следуй этим шагам:
- Запустите среду разработки Visual Studio 2022 Preview.
- Нажмите «Создать новый проект».
- В окне «Создать новый проект» выберите «ASP.NET Core Web API» из списка отображаемых шаблонов.
- Нажмите “Далее.
- В окне «Настроить новый проект» укажите имя и местоположение нового проекта.
- При желании установите флажок «Поместить решение и проект в один каталог», в зависимости от ваших предпочтений.
- Нажмите “Далее.
- В следующем окне «Дополнительная информация» снимите флажок «Использовать контроллеры…», поскольку в этом примере мы будем использовать минимальные API. В поле «Тип аутентификации» оставьте значение «Нет» (по умолчанию).
- Убедитесь, что флажки «Включить Docker», «Настроить HTTPS» и «Включить поддержку Open API» сняты, поскольку мы не будем здесь использовать ни одну из этих функций.
- Нажмите Создать.
Мы будем использовать этот проект веб-API ASP.NET Core 7 для создания минимального API и реализации фильтров обработчиков маршрутов в разделах ниже.
Что такое фильтры? Почему мы должны их использовать?
Фильтры позволяют запускать код на определенных этапах конвейера обработки запросов. Другими словами, фильтр — это фрагмент кода, который выполняется до или после выполнения метода действия. Например, вы можете использовать фильтр для регистрации каждый раз, когда кто-то обращается к веб-странице, или для проверки параметров запроса, отправленных в конечную точку.
Фильтры имеют ряд преимуществ:
- Фильтры повышают безопасность вашего приложения, позволяя отклонять запросы, не соответствующие определенным критериям (включая авторизацию).
- Фильтры могут помочь вам очистить ваш код, создавая повторно используемые функции и классы.
- Фильтры позволяют вам сосредоточиться на бизнес-логике вашего приложения вместо того, чтобы тратить время на написание кода для решения сквозных задач, таких как ведение журнала, обработка исключений и безопасность.
Почему нам следует использовать фильтры в минимальных API?
Вы можете воспользоваться фильтрами в минимальных API для написания кода, который может выполнять следующие действия:
- Выполняйте код до и после обработчика конечной точки.
- Проверяйте и редактируйте параметры при выполнении обработчика конечной точки.
- Проверьте поведение ответа обработчика конечной точки.
- Записывать метаданные запросов и ответов.
- Убедитесь, что запрос нацелен на поддерживаемую версию API.
- Проверьте запрос и параметры запроса.
Интерфейс IRouteHandlerFilter в ASP.NET Core 7.
Вы можете воспользоваться интерфейсом IRouteHandlerFilter, чтобы изменить запрос или ответ или сократить конвейер обработки запросов. Вы также можете добавить сквозные задачи, такие как аутентификация, авторизация и ведение журнала. Вкратце, вот чего вы можете достичь с помощью этого интерфейса:
- Напишите собственную логику для обработки входящих запросов.
- Перехватите запрос и измените объект запроса по мере необходимости.
- Внесите изменения в ответ перед его отправкой.
- Замкните запрос, что означает, что все оставшиеся фильтры действий не будут выполнены.
Следующий фрагмент кода иллюстрирует интерфейс IRoutehandler:
namespace Microsoft.AspNetCore.Http;
public interface IRouteHandlerFilter
{
ValueTask<object?> InvokeAsync(
RouteHandlerInvocationContext context,
RouteHandlerFilterDelegate next);
}
Создайте собственный фильтр обработчика маршрутов в ASP.NET Core 7.
Вы можете создать собственный класс фильтра через интерфейс IRouteHandlerFilter, как показано в листинге кода, приведенном ниже.
public class DemoFilter : IRouteHandlerFilter
{
private ILogger _logger;
public DemoFilter(ILoggerFactory loggerFactory)
{
_logger = logger;
}
public async ValueTask<object?> InvokeAsync(RouteHandlerInvocationContext context, RouteHandlerFilterDelegate next)
{
var text = context.GetParameters[0];
if (text.Equals("Error"))
{
_logger.LogInformation(“Error.”);
return Results.Problem("This is a minimal example of an error.");
}
_logger.LogInformation(“Success.”);
return await next(context);
}
}
Затем вам следует зарегистрировать фильтр как службу в файле Program.cs, используя следующий фрагмент кода.
builder.Services.AddSingleton<DemoFilter>();
Фильтр можно зарегистрировать с помощью RouteHandlerFilterDelegate или метода расширения AddFilter. В этом примере мы будем использовать метод расширения AddFilter. Напишите следующий фрагмент кода в файле Program.cs.
app.MapGet("/v1/MyDemoEndpoint{text}", “Hello”)
.AddFilter<DemoFilter>();
Создайте фильтр короткого замыкания в ASP.NET Core 7.
Часто вам может потребоваться короткое замыкание конвейера обработки запросов. Например, предположим, что вы создали приложение на основе микросервисов, и один из сервисов не отвечает. В этом случае все запросы к этому сервису завершатся неудачно. Вместо этого вы можете замкнуть конвейер обработки запросов и обратиться к какой-нибудь другой исправной службе.
Короткое замыкание часто является желаемым действием, чтобы избежать ненужной обработки. Например, если запрос генерируется для статических файлов, таких как HTML, CSS и JavaScript, вы можете написать фильтр, который будет перехватывать, обрабатывать и обслуживать этот запрос, одновременно сокращая остальную часть конвейера. Короткое замыкание останавливает конвейер обработки запросов и перенаправляет запрос на резервный метод или службу.
Другим примером короткого замыкания является шаблон автоматического выключателя в приложениях на основе микросервисов. Этот шаблон не позволяет приложению выполнять операцию, которая может привести к сбою. Обычно автоматические выключатели перенаправляют запросы на резервный метод, если у вас возникают проблемы со службой или методом службы. Таким образом, когда из-за сбоя службы возникает сбой, вы можете использовать автоматические выключатели для перенаправления запроса к резервным службам или методам.
Вот как вы можете реализовать собственный фильтр короткого замыкания для вашего минимального API:
public class MyShortCircuitFilter: IRouteHandlerFilter
{
public ValueTask<object?> InvokeAsync(
RouteHandlerInvocationContext context,
RouteHandlerFilterDelegate next)
{
return new ValueTask<object?>(Results.Json
(new { Message = "Terminated" }));
}
}
Фильтры позволяют запускать собственный код до или после определенного момента в конвейере обработки запросов. Они также помогают избежать дублирования кода в действиях. Интерфейс IRouteHandlerFilter — это специальный фильтр, который можно применить ко всему маршруту или к одному обработчику. Это позволяет вам получить доступ к объекту запроса, а затем изменить запрос или ответ по мере необходимости.