-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Html.Partial causes deadlocks and should be marked obsolete #7083
Description
So I've spent the last couple of days trying to figure out the source of deadlocks in our application, and it turns out that Html.Partial can cause deadlocks in ASP.NET Core 2.0, because it's implementation is:
var result = htmlHelper.RenderPartialAsync(partialViewName, htmlHelper.ViewData.Model, viewData: null);
result.GetAwaiter().GetResult();which is a classic misuse of async/await APIs due to the potential for deadlocks when you do synchronous blocking on a task.
Literally in our Razor view, changing:
@Html.Partial("../Shared/Navigation", new JamHost.ViewModels.NavigationViewModel
{
Entries = JamHost.Services.NavigationEntries.GetNavigationEntries(),
User = CurrentUser.IsAuthenticated ? await CurrentUser.GetUser() : null
})
to
@await Html.PartialAsync("../Shared/Navigation", new JamHost.ViewModels.NavigationViewModel
{
Entries = JamHost.Services.NavigationEntries.GetNavigationEntries(),
User = CurrentUser.IsAuthenticated ? await CurrentUser.GetUser() : null
})
is the difference between a deadlock and the page rendering okay, which is crazy because as a consumer, it means I can't trust any of the MVC API surface when it comes to "will using this function cause deadlocks?". There's no declaration or warning that using Html.Partial in Razor views can cause deadlocks, and the only reason I even thought of changing Html.Partial to Html.PartialAsync as a solution is because someone else also ran into this problem. Indeed at the moment we're fighting random scenarios where our application deadlocks and never continues serving any more requests, and because of this issue I'm likely to believe it is in fact just that half the MVC API surface we're using can cause deadlocks because of an implementation detail.
Anyway, any methods which can cause deadlocks like this should either be fixed, or be marked Obsolete telling the consumer to use the async version (as far as I'm aware all Razor views are async now anyway so there's no scenarios where the non-async versions should be used).