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);    
    }
 }