异步 PartialView 导致“ HttpServerUtility.Execute block...”异常

我有一个部分视图,它尝试使用异步... 从数据库检索 IEnumerable<Post>

方法

public static class PostService
{
public static int PostsPerPage = 50;


public static async Task<IEnumerable<Post>> GetRecentAsync(int page = 0)
{
return await entityFrameworkDbContext.Posts
.ToListAsync();
}
}

部分视图

public async Task<ActionResult> Recent(int page = 0)
{
return PartialView(await PostService.GetRecentAsync(page));
}

然后如果我试图打电话给它

@Html.Action("Recent", "Post")

我得到了下面的例外

在等待异步操作完成时阻塞执行。

描述: 在当前 Web 请求的执行过程中发生了一个未处理的异常。请查看堆栈跟踪,以获得有关错误的更多信息以及错误在代码中的起源位置。

异常详细信息: System.InvalidOperationException: HttpServerUtility.Execute 在等待异步操作完成时被阻止。

为什么我会得到这个错误? 它不应该工作吗?

55589 次浏览

Child actions must be invoked synchronously. Issue 601 I am also not aware of any recent updates to the current MVC libraries allowing this functionality.

A comment on Issue 601, hints at this functionality being added in MVC vNext, aka. MVC6. Child actions look to be replaced with ViewComponent which can be invoked asynchronously from a view as below. Full examples here and here

<div>
@await Component.InvokeAsync("YourComponent")
</div>

For more on MVC6 check out, http://www.asp.net/vnext/overview/aspnet-vnext/overview

Note: This answer is just a formality, so the question can be marked as answered

A workaround for this issue is to make the method synchronious as required by MVC, clear the SynchronizationContext, call the async method and wait for the result, then restore the context.

see my full aswer here

I had similar issue calling API for some social media website and fetching our last few posts and displaying them at the home page of one of our websites.

the work around this was to use JavaScript to fetch the data I want to display at the home page from the View (Or partial view you wish to display) and then use ID.innerHTML + = to hook the fetched data inside the home page as shown at the following code

 <div id="ID"></div>


<script>
var ID = document.getElementById('twitter');


var sendHttpRequest = (method, url) => {
var promise = new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();


xhr.open(method, url);


xhr.onload = () => {
resolve(xhr.response);
};


xhr.send();
});


return promise;
};


window.addEventListener('load', function () {
sendHttpRequest('GET', '////////////// the URL for the View (Or Partial View) /////////').then((responseData) => {ID.innerHTML += responseData})


})
</script>

Hope this will help someone who's looking for a faster solution for this issue.

Thanks