When to use @await Html.PartialAsync in a View in MVC 6

Solution 1:

This is actually a pretty interesting question and scenario. To a certain extent, async is the new hotness (though it's really not all that new). Entity Framework 6 hit with async methods and every... single... piece... of... documentation... suddenly starting using async for everything. I think we're seeing a little of the same here. MVC 6 supports async for things like rendering partials, so OMG we've all just have to use async now.

Async serves one very specific purpose. It allows the active thread to be returned to the pool to field other tasks while the current task is in a wait state. The key part of that is "wait state". Certain tasks are just flat out incompatible with async. CPU-bound work like complex financial analysis never allows the thread to enter a wait state so everything is effectively run as sync even if you set it up as async. On the other hand, things involving network latency (requesting a resource from a web API, querying a database, etc.) or that are I/O bound (reading/writing files, etc.) can at times have periods where the thread is waiting around for some other process to complete before it continues processing.

Looking specifically at rendering a partial, the only piece that's not entirely CPU-bound is reading the view file itself from the filesystem. While that's technically enough to make it eligible for async, how long is it really going to take to read what's essentially a text file that's probably less than 50KB max. By the time the thread is handed back to the pool, it's probably time to request it back, so you're actually using resources more inefficiently at that point.

Long and short, don't fall into the trap of "it can be done async, so I must do it async". Each use should be evaluated in terms of whether there's actually value in it. Async has a lot of overhead, and if you're only talking about a few milliseconds of wait time, it's probably not worth all that extra overhead.

Solution 2:

As per the ASP.NET MVC documentation on partial views. https://docs.asp.net/en/latest/mvc/views/partial.html

The PartialAsync method is available for partial views containing asynchronous code (although code in views is generally discouraged):

Also the note on the page.

If your views need to execute code, the recommended pattern is to use a view component instead of a partial view.

So you should use Partial and avoid PartialAsync, and if you find yourself with a PartialAsync you should question yourself whether you're doing something wrong, maybe you should be using a ViewComponent instead or move the logic from the view to the controller.

Solution 3:

With regards to "await Html.PartialAsync" - this link may help you - http://aspnetwebstack.codeplex.com/workitem/601 (follow the comments too) (as to what exactly was the problem before).

I am working on a public facing website being built on MVC 6 and "await Html.PartialAsync" is faster than "Html.Partial" - especially when the view contains lot of components.

Taking out the "await" out of Html.PartialAsync does not obviously work and Html.PartialAsync spits out the type name (ie, "System.Threading.Tasks.Task`1[Microsoft.AspNet.Mvc.Rendering.HtmlString]") instead of the actual view.

Solution 4:

Just to keep the thread up to date for those visiting in the age of asp.net core.

Currently, according to the documentation:

Partial and RenderPartial are the synchronous equivalents of PartialAsync and RenderPartialAsync, respectively. The synchronous equivalents aren't recommended because there are scenarios in which they deadlock. The synchronous methods are targeted for removal in a future release.

Full content: Partial views in ASP.NET Core

To get an idea about why this is an issue, you can take a look at this github entry:

https://github.com/aspnet/Mvc/issues/7083

But long story short it looks like the synchronous version of Partial simply calls async one with GetResult and that's a recipe for deadlocks in some scenarios.

To sum up, there is no real reason not to use the Async version. There are reasons not to use the sync ones. Even though there is little chance to actually run into deadlocks without huge load and fancy logic within the views.... But if you do, it will be terribly hard to debug and fix.

var result = htmlHelper.RenderPartialAsync(partialViewName, htmlHelper.ViewData.Model, viewData: null);
result.GetAwaiter().GetResult();