【问题标题】:Async OnActionExecuting in ASP.NET Core's ActionFilterAttributeASP.NET Core 的 ActionFilterAttribute 中的异步 OnActionExecuting
【发布时间】:2017-10-14 06:17:22
【问题描述】:

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


    【解决方案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

    【讨论】:

    • 其实it's in here在第二个代码块中
    • @grokky 基本实现检查参数并调用另外两个方法。如果您没有覆盖其他两种方法,则不需要调用它。
    • @grokky 你可以在这里查看源代码:github.com/aspnet/Mvc/blob/dev/src/…
    • 对于那些搜索代理是否抛出异常的人,从var result = await next();获取结果,然后检查result.Exception
    【解决方案2】:

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

    根据Docs

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

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

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

    【讨论】:

      【解决方案3】:

      更好的模式:

      public override async Task OnActionExecutionAsync(
          ActionExecutingContext context, 
          ActionExecutionDelegate next)
      {
          try
          {
                //do your async things here                 
          }
          finally
          {
              await base.OnActionExecutionAsync(context, next); <--- notice this!
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-10-11
        • 2015-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多