在MVC 5中调用异步方法的操作过滤器

13

我正在编写一个Action Filter(继承自ActionFilterAttribute),它使用HttpClientOnResultExecuted方法中向外部服务器POST数据。HttpClient有一个名为PostAsync的方法,它返回一个可等待的Task<HttpResponseMessage>

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
    using (var client = new HttpClient())
    {
        var task = client.PostAsync(GetUri(), GetContent());
        var result = task.Result; // blocking
    }
}

MVC 4中无法使用异步操作过滤器是一个已接受的答案。

在MVC 5中是否仍然如此,如果是,则调用此异步方法的最佳方式是什么,以避免阻塞线程?


1
不行,因为这样它就不再是一个覆盖了(方法定义本质上已经不同了)。这只是你正在添加的一个新方法,框架永远不会调用它。 - Chris Pratt
1
@ChrisPratt 正如我所说,先测试一下...在发表之前我已经测试过了。 - L.B
1
除非该方法能够返回一个 Task,否则它仍将同步运行。添加 async 并不能像魔术棒一样解决所有问题。 - Chris Pratt
2
哇,好吧,这里有一些理解上的问题。你用async修饰一个方法并运行它,并不意味着它是异步运行的。我非常确定你让那段代码运行了,但它绝对没有异步运行。也许你并不真正理解什么是异步?它只是意味着该方法将放弃其线程以供其他进程使用,同时等待操作完成。然后,一旦操作完成,它请求线程回来并继续执行。同步方法则在整个过程中保持线程。 - Chris Pratt
1
你们两个都是对的,但结果行为可能会非常错误。 过滤器将运行,但是在异步过滤器完成之前,管道将继续执行。例如,假设您想包含外部调用的结果(或者检查它并返回其他HTTP响应代码):这将失败,因为在异步调用返回时,结果已经在进行中了(这就是异步void的作用,“点火并忘记”)。 - Mark Sowul
显示剩余15条评论
2个回答

11

是的,这仍是事实。Web API 2支持异步操作过滤器,但MVC 5仍不支持。我最近也因此感到沮丧。目前,您需要在操作过滤器内将异步方法转换为同步方法运行,或者在每个需要异步操作的操作中重复使用会在操作过滤器中执行的异步代码,然后将其作为异步代码运行。


5
哎呀,确实不太理想。这真是太遗憾了,这个功能如此缺乏。 - dav_i
我同意,而且似乎添加这样的功能也很容易。希望vNext会支持它,但是,vNext本来就完全不同。 - Chris Pratt
1
它在vNext中已经得到支持。新的MVC/WebAPI控制器都支持异步操作过滤器以及异步子操作(在vNext中称为“视图组件”)。当前ASP.NET上的MVC与ASP.NET核心太过紧密(同步方式),因此我不希望在vNext之前修复这个问题。 - Stephen Cleary
@StephenCleary:好知道。我听说过这个传言,但还没有得到确认。 - Chris Pratt
不,这里的就是全部内容。MVC 5及其之前版本不支持异步操作过滤器,而Core则支持。 - Chris Pratt
显示剩余2条评论

0

有个人在这里进行了一种“向后移植”

https://github.com/jdaigle/Hydrogen.Extensions.Mvc5

我没有尝试过,也不能推荐它,但如果你正在转向.NET Core,考虑一下可能是值得的。幸运的是,我成功地从我的扩展中删除了所有异步代码 - 这次。


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