Фильтры действий: настройка привязки модели и результатов действий¶
Фильтры действий запускаются после привязки модели, до выполнения метода действия. Благодаря своему расположению эти фильтры получают доступ ко всем аргументам метода. Кроме этого, они запускаются после выполнения метода действия и при желании могут изменить или заменить IActionResult, возвращаемый действием.
Note
фильтры действий не выполняются для Razor Pages
ASP.NET Core включает в себя несколько стандартных фильтров действий, один из которых — ResponseCacheFilter, задающий заголовки кэширования для ответов.
Создадим два специальных фильтра для нашего контроллера:
ValidateModelAttribute— возвращаетBadrequestResult, если состояние модели не является валидным;EnsureRecipeExistsAttribute— будет проверять, что рецепт существует, используя аргументid.
В случае использования атрибута [ApiController] проверка и возврат кода 400 Bad Request происходит автоматически, однако, если использование этого атрибута невозможно, поможет фильтр ValidateModelAttribute:
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
}
Отметим следующее:
- Наследуемся от абстрактного класса
ActionFilterAttribute. Он реализует интерфейсыIActionFilterиIResultFilter, а также их асинхронные аналоги1, поэтому можно переопределить только нужный метод; - фильтры действий запускаются после привязки модели, поэтому
context.ModelStateсодержит ошибки, если привязка не удалась; - При задании
context.Resultвыполнение действия и более поздних фильтров будет отменено, однако более ранние фильтры выполнятся, как обычно.
Теперь реализуем EnsureRecipeExistsAttribute:
public class EnsureRecipeExistsAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var service = (RecipeService) context.HttpContext.RequestServices.GetService(typeof(RecipeService));
var recipeId = (int) context.ActionArguments["id"];
if (!service.DoesRecipeExist(recipeId))
{
context.Result = new NotFoundResult();
}
}
}
Здесь мы получаем экземпляр RecipeService2 и значение параметра id, после чего проверяем, существует ли рецепт.
Особый случай для фильтров действий¶
При использовании базового класса ControllerBase для контроллера, можно переопределить методы OnActionExecuting и OnActionExecuted этого класса; они будут запускаться на этапе фильтра действий для каждого действия контроллера. Метод OnActionExecuting будет выполняться перед всеми другими фильтрами действий, а OnActionExecuted - после.
-
здесь сказано, что нельзя реализовывать и синхронную и асинхронную версию фильтра, и это по-прежнему верно; в документации сказано, что можно переопределить либо один или оба синхронных метода, либо асинхронный, но нельзя переопределять асинхронный и синхронные методы одновременно. ↩
Дата создания : 3 октября 2022 г.