我们希望在所有页面的底部显示我们后端服务的版本详细信息。
3个后端服务是异步webapi(2.2)调用,我们需要让这3个异步调用将日期聚合到模型中,然后将其传递给View。
如果我将此作为(非子)控制器操作的一部分,代码将工作并显示数据。
但是,尝试在每个页面的底部显示此数据(子操作)会产生几种不同的异步死锁类型条件。
子操作并调用_layout.cshtml
read
由于请求没有结束,这导致似乎是死锁,
使用ActionFilter
//ControllerAction
[ChildActionOnly]
public ActionResult VersionInfo()
{
var version = _versionInfoViewModelMapper.Map().Result;
return View(version);...
}
//Layout.cshtml
@if(Request.IsAuthenticated)
{
Html.RenderAction("VersionInfo", "Utils");
}
使用上面的过滤器将数据传递给随后使用的ViewBag,给出相同的无限通话。
如果我在异步调用中不使用.Result,则会出现错误
HttpServerUtility.Execute在等待异步时被阻止 操作完成。
有没有办法解决这个问题?可能通过使用Global.asax Application_PostAuthenticateRequest或类似事件?
答案 0 :(得分:-1)
问题在于:
_versionInfoViewModelMapper.Map().Result;
如果设置了Task.Result
(在ASP环境中都是如此),则调用Task.Wait()
和SynchronizationContext
可能会导致严重的死锁。
而是使用方法的异步版本:
public async Task<ActionResult> VersionInfo()
{
var version = await _versionInfoViewModelMapper.Map();
return View(version);...
}
有关此问题的详细信息,请参阅this Stephen Cleary blog post