ASP.NET Core 的 ActionFilterAttribute 中的异步 OnActionExecuting
Async OnActionExecuting in ASP.NET Core's 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()
?
是吗?我不确定,因为我找不到这方面的文档。
异步过滤器的工作方式有点不同:首先执行必须在动作之前执行的代码,调用 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
Asynchronous filters always take precedence over the synchronous filter implementations.
根据 Docs:
- 建议实现过滤器接口的同步或异步版本,而不是同时实现。运行时首先检查过滤器是否实现了异步接口,如果是,它会调用它。如果不是,它调用同步接口的方法。如果在一个 class 中同时实现异步和同步接口,则只调用异步方法。
但是,您可以同时拥有两者。例如:
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);
}
}
更好的模式:
public override async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
try
{
//do your async things here
}
finally
{
await base.OnActionExecutionAsync(context, next); <--- notice this!
}
}
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()
?
是吗?我不确定,因为我找不到这方面的文档。
异步过滤器的工作方式有点不同:首先执行必须在动作之前执行的代码,调用 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
Asynchronous filters always take precedence over the synchronous filter implementations.
根据 Docs:
- 建议实现过滤器接口的同步或异步版本,而不是同时实现。运行时首先检查过滤器是否实现了异步接口,如果是,它会调用它。如果不是,它调用同步接口的方法。如果在一个 class 中同时实现异步和同步接口,则只调用异步方法。
但是,您可以同时拥有两者。例如:
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);
}
}
更好的模式:
public override async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
try
{
//do your async things here
}
finally
{
await base.OnActionExecutionAsync(context, next); <--- notice this!
}
}