ASP.NET Core 的 ActionFilterAttribute 中的异步 OnActionExecuting

问题描述 投票:0回答:3

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()
吗?

是这样吗?我不确定,因为我找不到这方面的文档。

c# asp.net-core action-filter
3个回答
111
投票

异步过滤器的工作方式有点不同:首先执行必须在操作之前执行的代码,调用

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://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters#implementation


5
投票

异步过滤器始终优先于同步过滤器实现。

根据文档

  • 建议实现过滤器接口的同步版本或异步版本,而不是同时实现。运行时首先检查过滤器是否实现了异步接口,如果是,则调用该接口。如果没有,它将调用同步接口的方法。如果一个类中同时实现了异步和同步接口,则仅调用异步方法。

但是,您可以同时拥有两者。例如:

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


1
投票

更好的模式:

public override async Task OnActionExecutionAsync(
    ActionExecutingContext context, 
    ActionExecutionDelegate next)
{
    try
    {
        // logic before action goes here
    }
    finally
    {
        // await base.OnActionExecutionAsync(context, next); //dont
        await next(); // the actual action

        // logic after the action goes here
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.