В ASP.NET Core 7 мы можем воспользоваться недавно представленным интерфейсом IEndpointFilter для создания фильтров и присоединения их к конечным точкам в наших минимальных 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.
- Нажмите «Создать новый проект».
- В окне «Создать новый проект» выберите «ASP.NET Core Web API» из списка отображаемых шаблонов.
- Нажмите “Далее.
- В окне «Настроить новый проект» укажите имя и расположение нового проекта.
- При желании установите флажок «Поместить решение и проект в один каталог», в зависимости от ваших предпочтений.
- Нажмите “Далее.
- В следующем окне «Дополнительная информация» выберите «NET 7.0 (Current)» в качестве платформы и снимите флажок «Использовать контроллеры…», поскольку в этом примере мы будем использовать минимальное количество API. Оставьте для параметра «Тип аутентификации» значение «Нет» (по умолчанию).
- Убедитесь, что флажки «Включить поддержку OpenAPI», «Включить Docker», «Настроить для HTTPS» и «Включить поддержку Open API» не отмечены, так как мы не будем использовать эти функции здесь.
- Щелкните Создать.
Мы будем использовать этот проект веб-API ASP.NET Core 7 для создания минимального API и реализации фильтров конечных точек в разделах ниже.
Что такое фильтр конечной точки?
Фильтр — это код, который можно запускать в разных точках конвейера обработки запросов, до или после действия. Например, вы можете использовать фильтр для проверки авторизации или параметров запроса или для записи каждого обращения к веб-странице.
Фильтр конечных точек можно вызывать для действий и конечных точек маршрута. Конечная точка — это URL-адрес, который является точкой входа для приложения, например http://example.com/.
Ключевые преимущества фильтров включают повышенную безопасность и упрощение вашей кодовой базы за счет повторного использования кода. Например, вы можете использовать фильтры, чтобы:
- Отклонять запросы, которые не соответствуют определенным критериям.
- Создавайте многократно используемые функции и классы.
- Сосредоточьтесь на бизнес-логике вашего приложения вместо того, чтобы тратить время на написание кода для сквозных задач.
- Выполнять код до и после обработчика конечной точки.
- Метаданные запроса и ответа журнала.
- Проверка запроса и параметров запроса.
Фильтр конечной точки позволяет вам перехватывать входящий запрос, изменять его, обходить его и даже объединять ваши сквозные задачи в одном месте. Типичными примерами междисциплинарных проблем, которые могут быть решены в одном классе, являются авторизация, проверка и обработка исключений.
Интерфейс IEndpointFilter в ASP.NET Core 7
В ASP.NET Core 7 представлен новый интерфейс с именем IEndpointFilter, который можно использовать для изменения запроса, изменения ответа или короткого замыкания конвейера запросов. Интерфейс IEndpointFilter можно использовать для добавления информации к входящим запросам до их обработки конечной точкой.
Интерфейс IEndpointFilter определен в пространстве имен Microsoft.AspNetCore.Http, как показано ниже.
public interface IEndpointFilter
{
ValueTask<object?> InvokeAsync(
EndpointFilterInvocationContext context,
EndpointFilterDelegate next);
}
Почему я должен использовать интерфейс IEndpointFilter?
Интерфейс IEndpointFilter используется для добавления функциональных возможностей конечной точке HTTP. Это простой интерфейс только с одним методом InvokeAsync, который может добавлять пользовательскую логику в конвейер запроса/ответа.
Вы можете использовать интерфейс IEndpointFilter, если хотите изменить запрос или ответ в определенной точке конвейера. Вы можете использовать его, чтобы поместить все ваши сквозные компоненты, такие как ведение журнала, аутентификация, авторизация и шифрование, в одном месте, где вы можете поддерживать их, не изменяя какую-либо другую часть кода вашего приложения, которая использует эти компоненты.
Создайте фильтр конечной точки в ASP.NET Core 7.
Вы можете зарегистрировать фильтр с помощью делегата, который принимает EndPointFilterInvocationContext в качестве параметра и возвращает EndpointFilterDelegate. Экземпляр EndPointFilterInvocationContext предоставляет доступ к HttpContext текущего запроса.
В следующем фрагменте кода показано, как можно создать простой фильтр конечной точки, возвращающий некоторый текст. Обратите внимание, как HttpContext использовался для получения заголовков запроса.
string AuthorName(string author) => $"Name of author: {author}";
app.MapGet("/endpointfilterexample/{author}", AuthorName)
.AddEndpointFilter(async (invocationContext, next) =>
{
var httpContext = invocationContext.HttpContext;
var requestHeaders = httpContext.Request.Headers;
var author = invocationContext.GetArgument<string>(0);
return await next(invocationContext);
});
Когда вы выполняете предыдущий фрагмент кода, заголовки запроса будут отображаться, как показано на рисунке 1 ниже.
Рис. 1. Фильтры конечных точек ASP.NET Core 7 в действии.
Объединение нескольких фильтров конечных точек в ASP.NET Core 7
В следующем коде показано, как несколько фильтров конечных точек могут быть объединены в цепочку в конечной точке по умолчанию.
app.MapGet("https://www.infoworld.com/", () =>
{
return "Demonstrating multiple filters chained together.";
})
.AddEndpointFilter(async (endpointFilterInvocationContext, next) =>
{
app.Logger.LogInformation("This is the first filter.");
var result = await next(endpointFilterInvocationContext);
return result;
})
.AddEndpointFilter(async (endpointFilterInvocationContext, next) =>
{
app.Logger.LogInformation("This is the second filter.");
var result = await next(endpointFilterInvocationContext);
return result;
})
.AddEndpointFilter(async (endpointFilterInvocationContext, next) =>
{
app.Logger.LogInformation("This is the third context.");
var result = await next(endpointFilterInvocationContext);
return result;
});
Когда вы выполняете конечную точку, три фильтра конечных точек будут выполняться один за другим.
Создайте собственный фильтр в минимальном API в ASP.NET Core 7.
Вы также можете создавать собственные фильтры, реализовав интерфейс IEndpointFilter, как показано во фрагменте кода, приведенном ниже.
public class MyCustomFilter : IEndpointFilter
{
public async ValueTask<object?> InvokeAsync(
EndpointFilterInvocationContext context,
EndpointFilterDelegate next
)
{
if (context.HttpContext.GetRouteValue("city") is string city)
{
return Results.Ok($"The name of the city is: {city}");
}
return await next(context);
}
}
app.MapGet("/demo/{city}", () =>
{
return "Execute filters in a chain.";
})
.AddEndpointFilter<MyCustomFilter>();
Чтобы получить доступ к параметрам, связанным с конкретным HTTP-запросом, вы можете использовать метод GetArguments объекта EndpointFilterInvocationContext. Если у вас есть несколько фильтров, вы можете зарегистрировать их, используя следующий код в файле Program.cs.
app.MapGet("https://www.infoworld.com/", () =>
{
return "This is a sample text.";
})
.AddEndpointFilter<MyCustomFilterA>()
.AddEndpointFilter<MyCustomFilterB>()
.AddEndpointFilter<MyCustomFilterC>();
Фильтры в ASP.NET Core позволяют запускать пользовательский код до или после определенного момента в конвейере обработки запросов. Вы можете воспользоваться преимуществами фильтров конечных точек, чтобы сократить выполнение конечных точек, или внедрить логику проверки в свой минимальный API. Я буду обсуждать фильтры конечных точек более подробно в следующем посте здесь.