Ответ
Фильтры в ASP.NET Core — это компоненты, которые выполняют код до или после определенных этапов конвейера обработки запроса (pipeline). Они позволяют инкапсулировать сквозную функциональность (cross-cutting concerns), такую как авторизация, логирование, валидация, кэширование.
Фильтры выполняются в строгом порядке, известном как Pipeline фильтров:
- Authorization Filters → 2. Resource Filters → 3. Action Filters → 4. Exception Filters → 5. Result Filters
Основные типы фильтров:
1. Authorization Filters (IAuthorizationFilter, IAsyncAuthorizationFilter)
- Цель: Определить, авторизован ли пользователь для доступа к ресурсу.
- Выполняется: Первыми, до привязки модели и выполнения действия.
- Пример:
[Authorize],[AllowAnonymous]. - Зачем свой? Для реализации кастомной политики доступа (например, на основе роли и региона).
2. Resource Filters (IResourceFilter, IAsyncResourceFilter)
- Цель: Обработка запроса до и после остальных фильтров в конвейере. Идеальны для кэширования или валидации состояния ресурса.
- Выполняется: После Authorization, но до Model Binding. Имеют метод
OnResourceExecuting(до) иOnResourceExecuted(после). - Пример использования: Короткое замыкание конвейера (early exit) для возврата закэшированного результата.
public class CustomCacheResourceFilter : IAsyncResourceFilter
{
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{
// 1. ДО выполнения остального конвейера: проверяем кэш
var cacheKey = GenerateCacheKey(context.HttpContext.Request);
if (_cache.TryGetValue(cacheKey, out var cachedResult))
{
context.Result = cachedResult as IActionResult; // Короткое замыкание
return;
}
// 2. Позволяем конвейеру выполниться
var executedContext = await next();
// 3. ПОСЛЕ выполнения: сохраняем результат в кэш
if (executedContext.Result is OkObjectResult okResult)
{
_cache.Set(cacheKey, okResult.Value, TimeSpan.FromMinutes(5));
}
}
}
3. Action Filters (IActionFilter, IAsyncActionFilter)
- Цель: Логика, специфичная для действия контроллера. Выполняются до и после вызова метода действия, но после привязки модели.
- Использование: Валидация модели, логирование параметров, изменение аргументов или результата действия.
- Глобальный пример:
[ServiceFilter(typeof(LoggingActionFilter))].
4. Exception Filters (IExceptionFilter, IAsyncExceptionFilter)
- Цель: Глобальная обработка необработанных исключений, возникших в контроллере, фильтрах или привязке модели.
- Выполняется: Только при возникновении исключения.
- Важно: Не перехватывают исключения в Middleware или при генерации результата (для этого есть
UseExceptionHandlermiddleware). - Пример: Отправка специфичных ошибок API в определенном формате (JSON).
5. Result Filters (IResultFilter, IAsyncResultFilter)
- Цель: Логика, выполняемая до и после выполнения результата действия (например, перед рендерингом представления).
- Выполняется: После метода действия, но до выполнения
IActionResult(вызоваView()илиJson()). - Использование: Изменение HTTP-заголовков, форматирование ответа, логирование результата.
Способы применения фильтров:
- На уровне действия:
[TypeFilter(typeof(MyActionFilter))]на методе контроллера. - На уровне контроллера: Атрибут применяется ко всем действиям в контроллере.
- Глобально: Регистрация в
Program.csилиStartup.ConfigureServices:services.AddControllers(options => { options.Filters.Add(new MyGlobalFilter()); // Экземпляр options.Filters.Add<MyGlobalFilter>(); // Тип (будет разрешен через DI) });
Ключевое правило: Фильтры, зарегистрированные глобально, применяются ко всем действиям. Фильтры на контроллере/действии выполняются в порядке: глобальные → контроллер → действие (для OnActionExecuting), и в обратном порядке для OnActionExecuted.