Async OnActionExecuting в ASP.NET Core ActionFilterAttribute
ASP.NET Core ActionFilterAttribute
имеет следующие значения:
public virtual void OnActionExecuting(ActionExecutingContext context);
public virtual void OnActionExecuted(ActionExecutedContext context);
public virtual Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next);
Мне нужна асинхронная версия OnActionExecuting
, которой не существует.
Однако у меня возникает ощущение, что вместо этого я могу использовать OnActionExecutionAsync
, так как он также имеет аргумент ActionExecutingContext
.
Правильно ли, что, несмотря на название, они срабатывают в одном и том же месте процесса?
Кроме того, что мне нужно сделать со next
аргументом? Как только я закончил с моими вещами, мне просто нужно позвонить в await next()
?
Это оно? Я не уверен, поскольку я не могу найти документы для этого.
Ответы
Ответ 1
Асинхронные фильтры работают по-другому: сначала выполните код, который должен быть выполнен перед действием, вызовите next()
для фактической логики и, наконец, добавьте код, который будет выполнен после действия.
public async Task OnActionExecutionAsync(ActionExecutingContext context,
ActionExecutionDelegate next)
{
// logic before action goes here
await next(); // the actual action
// logic after the action goes here
}
Документация находится здесь: https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters#implementation
Ответ 2
Асинхронные фильтры всегда имеют приоритет над реализациями синхронных фильтров.
Согласно Документам:
- Он рекомендовал реализовывать либо синхронную, либо асинхронную версию интерфейса фильтра, а не оба. Среда выполнения сначала проверяет, реализует ли фильтр асинхронный интерфейс, и если это так, то вызывает его. Если нет, он вызывает метод синхронного интерфейса. Если в одном классе реализованы как асинхронные, так и синхронные интерфейсы, вызывается только асинхронный метод.
Тем не менее, вы можете иметь оба. Например:
public class TimestampFilter : IActionFilter, IAsyncActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
context.ActionDescriptor.RouteValues["timestamp"] = DateTime.Now.ToString();
}
public void OnActionExecuted(ActionExecutedContext context)
{
var ts = DateTime.Parse(context.ActionDescriptor. RouteValues["timestamp"]).AddHours(1).ToString();
context.HttpContext.Response.Headers["X-EXPIRY-TIMESTAMP"] = ts;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
this.OnActionExecuting(context);
var resultContext = await next();
this.OnActionExecuted(resultContext);
}
}