MVC 4中的异步操作过滤器

33

我有一个操作筛选器,当在某些特定条件下使用时,必须执行Web服务调用以确保当前状态有效。最初似乎这是异步/等待的理想选择,但我遇到了困难:

假设请求地址为:/Test/FilteredAction

  • MyCustomActionFilter 开始执行
    • 到达第一个“await”语句
  • TestController.FilteredAction 开始执行
  • MyCustomActionFilter 恢复执行

传统上,我希望操作筛选器在控制器操作开始执行之前恢复执行并完成,但这并没有发生。

现在我假设这是因为我正在使用:

public class MyCustomActionFilter : ActionFilterAttribute 
{
    public override **async** void OnActionExecuting(FilterContext context) 
    {
        var foo = await WebServiceCall();
    }
}

所以我想问的是:MVC 4中是否有内置的异步感知的ActionFilter类,或者我应该只是在此处阻塞调用?


你尝试过应用 ayende 的博客文章 中描述的方法吗? - ITmeze
我最近发布了一个库,它为异步过滤器提供了适当的支持(大量基于来自ASP.NET MVC Core的代码)。源代码也可在此处获得:https://github.com/jdaigle/Hydrogen.Extensions.Mvc5。 - Joseph Daigle
3个回答

43

MVC没有与async兼容的动作过滤器(但WebAPI有一个)。

目前,建议您在OnActionExecuting中使用阻塞调用。希望MVC在未来会有更好的解决方案。

更新:您可以在此处投票,要求MVC团队添加async过滤器。


2
+1 @DannyChen,调用服务进行验证的筛选器是需要异步支持的典型例子。问题不在于同步筛选器无法工作,而是异步筛选器可以更好地工作。 - Alexei Levenkov
我花了一整天的时间尝试在"OnActionExecuting"方法中让异步代码正常工作。但是一直出现死锁问题。我们真的需要在这里支持异步操作。我正在尝试检查和更新分布式缓存的示例。 - Paul Fryer
@DannyChen 一种诊断过滤器,可在不饥饿线程的情况下向处理请求添加额外的延迟时间。 - John
3
这里的“vote here”链接已经失效了 - 目前是否有关于此的最新支持消息?如果仍然有投票的地方(或者GitHub上的+1问题),我会为它投一票。我搜索了一段时间,但没有找到任何信息。 - Rob Hruska
2
@RobHruska async 过滤器将适用于 ASP.NET vNext 的 MVC。据我所知,他们没有计划将其添加到当前的 MVC 分支中。 - Stephen Cleary
显示剩余2条评论

1
你不能拥有异步的过滤器,但你可以拥有异步的事件处理程序
异步事件处理程序可以执行繁重的异步工作,写入HttpApplication.HttpContext.Items,然后你的同步过滤器可以后处理或验证结果。
你可以在Global.asax.cs中注册事件处理程序,也可以创建并注册HTTP模块
(所有过滤器都在PreRequest和PostRequest事件之间执行。)

0

不,MVC没有异步过滤器,但这是可行的。

ASP.NET MVC 过滤器依赖于有序的概念,如果指定了一个过滤器(请参阅Order属性IMvcFilter接口),则保证按照一定的顺序执行。

需要解决的问题如下:

  • 对于现有的非异步过滤器(至少没有以这种方式实现,因为没有其他方法),它们是否会获得自己的任务或继续上一个任务?这是一个重要的问题需要回答,因为您必须权衡不在另一个线程上继续下一个过滤器的好处与保留该线程,而其他请求可能会使用它。

  • 对于具有相同顺序指定的过滤器,它们是并行执行还是依次执行?使方法异步打开了更多的可能性(即使以前可以使用非异步签名完成),这绝对是一项架构变更,可能会影响性能和预期结果。这里的答案并不简单,必须基于测试和向后兼容性。


5
我认为这并不复杂。过滤器可以短路结果,因此无论它们是同步还是异步,您都只能按顺序运行它们。这是现有的行为,因此不会产生任何向后兼容性问题。 - Jeremy Rosenberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接