ASP.NET MVC 4 async child action - asp.net-mvc

I have an ASP.NET MVC 4 application targeting .NET 4.5. One of our child actions makes a call out to a web service using HttpClient.
Since we're blocking on IO waiting for the HttpClient response, it makes a great deal of sense to convert the code to the async/await pattern. However, when MVC 4 attempts to execute the child action, we get the following error message:
HttpServerUtility.Execute blocked while waiting for an asynchronous operation to complete.
At first glance, it appears as though MVC 4 does not support async/await within a child action. The only remaining option is to run using synchronous code and force a "Wait" on the async task.
As we all know, touching .Result or .Wait() on an async task in an ASP.NET context will cause an immediate deadlock. My async logic is wrapped in a class library, so I can't use the "await blah.ConfigureAwait(false)" trick. Remember, tagging "async" on the child action and using await causes an error, and that prevents me from configuring the await.
I'm painted into a corner at this point. Is there any way to consume async methods in an MVC 4 child action? Seems like a flat out bug with no workarounds.

There are still parts of MVC that aren't async-friendly; I hope these will be addressed in the future. Please do create a Connect or UserVoice issue for this.
My async logic is wrapped in a class library, so I can't use the "await blah.ConfigureAwait(false)" trick.
You probably should add ConfigureAwait(false) to the calls in your class library (if you can).
You could also hack up an alternate solution. If your class library method doesn't need the ASP.NET context, then you could have a thread pool thread do the (a)waiting for you:
try
{
var result = Task.Run(async () => { await MyHttpRequest(...); }).Result;
}
catch (AggregateException ex) { ... }
The effect is similar to ConfigureAwait(false): since MyHttpRequest runs in a thread pool context, it will not attempt to enter the ASP.NET context when it completes.

The format of Stephen's answer didn't quite work for me (maybe it's an async noob problem, but hey).
I had to do write the async expression in this format to get a strongly typed return value.
Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;

Related

Session_Start and ASP.Net Async SessionState Module

We recently integrated the ASP.Net Async SessionState Module and have started seeing null ref exceptions in our Global.asax Session_Start event handler.
I can't replicate it locally, and it doesn't appear to happen all the time in live, but I believe this is when we attempt to access HttpContext.Current in Session_Start. My guess is HttpContext.Current is sometimes null, because Session initialization is asynchronous.
Any suggestions as to how to address?
Maybe the answer is too simple, but I have also seen this from time to time, and I'd suggest that you safeguard your code inside the Session_Start event like
if (HttpContext.Current !== null)
{
// do your actions with the Current object
}
else
{
// possibly add some logging here to see what's going on
}
If you notice it is just a race condition, your code will react properly and not just end up in a NullReferenceException.
Safeguarding it like this is in this particular case better than adding Elvis operators (?.) everywhere you're referencing it because that will lead into more complex scenarios for your testing/troubleshooting. In other cases, however, this operator is quite useful, for example in this different context.
Additionally, In the link you provided, I saw the hint "To implement your own async sessionstate provider which works with Microsoft.AspNet.SessionState.SessionStateModule, all you need to do is to implement a concrete SessionStateStoreProviderAsyncBase class which is included in the Microsoft.AspNet.SessionState.SessionStateModule NuGet package."
Maybe you just need to implement that class rather than using Session_Start - because here is always a HttpContext given as parameter and Session_Start is just there for backwards-compatibility?

Why do you use async if you don't promote it to the controller?

I'm trying to figure out how to use async/await in C# in my Asp.Net MVC.
The main point seems to be that it helps asp.net for releasing threads from the worker pool when you are doing IO (so they can process other stuff). For doing so you have to promote the async/await modifier from the method doing the IO call up to the controller action (you better have just a few layers).
Is there any point in using this feature without promoting the async/await up to my controller ? (by adding Task.Wait after a call to an Async method for instance).
The answer is "yes", but using Task.Wait() in an action is not a good idea because it can lead to a deadlock situation.
Consider the following from the guide, Async/Await Best Practice by Stephen Cleary:
Figure 3 A Common Deadlock Problem When Blocking on Async Code
public static class DeadlockDemo
{
private static async Task DelayAsync()
{
await Task.Delay(1000);
}
// This method causes a deadlock when called in a GUI or ASP.NET context.
public static void Test()
{
// Start the delay.
var delayTask = DelayAsync();
// Wait for the delay to complete.
delayTask.Wait();
}
}
However, if you add ConfigureAwait(false) to DelayAsync() like this:
await Task.Delay(1000).ConfigureAwait(false)
then you can avoid deadlocks, as explained in the article:
Aside from performance, ConfigureAwait has another important aspect: It can avoid deadlocks. Consider Figure 3 again; if you add “ConfigureAwait(false)” to the line of code in DelayAsync, then the deadlock is avoided. This time, when the await completes, it attempts to execute the remainder of the async method within the thread pool context. The method is able to complete, which completes its returned task, and there’s no deadlock. This technique is particularly useful if you need to gradually convert an application from synchronous to asynchronous.
Do not use Task.Wait as it can deadlock or produce an AggregateException. If you need to do this then you should use Task.WhenAll which is non-blocking.
Generally though, it is safest to use async code end-to-end. The benefit of using async away through the entire stack is that your code will be easier to debug and error handling much simpler.
So yes, if you are going to use async/await - include it in your controller and avoid using blocking code like Task.Wait.

Make ActionResult Asynchronous To Increse Performance And elimate Flickering

I want to make this Action Asynchronous,Can Anyone Help On this.
[HttpGet]
public ActionResult LoadAddressDetail(int? whId)
{
try
{
return Json(new
{
GridData = wareHouseMasterService.LoadAddressGrid(GetCommonProperty(), whId ?? 0, DataManager.CustomerType, DataManager.CustomerTypeCode.WAREHOUSE.ToString()),
Status = true
}, JsonRequestBehavior.AllowGet);
}
catch (Exception e) { this.loggerService.Error(e); return Json(false, JsonRequestBehavior.AllowGet); }
}
Since I am Using Three httpget Methods executed at one page load and the screen flickers Three Times.So I need parallel Processing.
Not sure exactly what you're looking for here. Making an action async is as simple as adding the async keyword and returning Task<ActionResult>:
public async Task<ActionResult> LoadAddressDetail(int? whId)
Of course, then, you must await something. The only thing I see that seems to do any work is wareHouseMasterService.LoadAddressGrid, but you've provided no details about what this does. Generally speaking, you would need to make this method async, as well, or add an async version of it. Then, you would simple do:
GridData = await wareHouseMasterService.LoadAddressGridAsync(...),
All that said, there's a big gotcha to keep in mind. Async, in the context of a web request, isn't the same thing as parallel processing, and it also does not make anything happen "faster". Additionally, there's a minor performance impact from using async, as there's overhead that goes along with that. In other words, simply making this action action async does not really in fact serve any other your mentioned goals.
The true reason to use async is to allow your web server to handle load more efficiently. When the thread handling the request is in a wait-state, async allows the thread to be returned to the pool to field other requests. Since there's a ceiling to the amount of threads a web server can spawn, and therefore the number of requests it can handle simultaneously, async gives you some extra head room when the server is under load. That's pretty much it, though.
That said, if you're trying all this out in development, using IIS Express, it's important to realize that IIS Express is single-threaded. In other words, requests are queued and handled serially, since raw performance is not a real factor in development. Therefore, in this situation, your three AJAX requests are being processed one at a time, rather than in parallel as they likely would be in full IIS, and that may be the source of what you're experiencing. Async may help here, but not necessarily. Regardless, it's only an issue in development.
Short of all that, you need to look at your JavaScript and ensure that you are doing things in an optimized way such that the AJAX requests are processed efficiently. There's also ways to minimize the flash of unstyled content issues apart from simply making everything happen quicker. However, since you've posted no code in this regard, there's not more that can be said.

Does TransactionScope flow across async continuations without the original context?

I'm developing an ASP.NET MVC5 application and I have the following situation:
Async controller method calls custom async method 1+ times, each Task object being stored successively in a List
Each custom async method call establishes its own top-level TransactionScope with TransactionScopeAsyncFlow.Enabled
Each custom async method call performs transactional work, then awaits DbContext.SaveChangesAsync()
While this is occurring, the controller method performs its own transactional work within its own unrelated TransactionScope, then awaits Task.WhenAll()
The question arises from using ConfigureAwait(false) when awaiting DbContext.SaveChangesAsync(). Each call to the custom async method starts in the controller method's ASP.NET request context but I don't see any need to recapture it when SaveChangesAsync() returns EXCEPT if it's going to mess up the current transaction. This is important because if an unrecoverable exception occurs in the controller method before I await Task.WhenAll, I need to cancel the async Tasks within a catch block, which means instead of awaiting Task.WhenAll() I'm forced to use the blocking method Task.WaitAll(), which I'm pretty sure will deadlock if the async Tasks are trying to recapture the original request context.
Sorry if this is a repeat question. I did quite a bit of searching and couldn't get a clear answer. Feel free to tell me this is bad programming or whatever, just at least suggest an alternative and leave my mom out of it. Thanks!

How to set ViewBag for _Layout in MVC4 using async in every action

The usecase is simple. Info for logged in user is displayed in _Layout.cshtml. That info needs to be refreshed every time.
I found two ways to do that
Have BaseController and in its OnActionExecuting method set ViewBag.UserInfo = ...; which is later used in _Layout.cshtml
In _Layout.cshtml do #{Html.RenderAction("GlobalUserInfo", "UserInfo");}
The problem is that these two ways fail miserably with deadlocks or exceptions if UserInfo is returned from an async public async Task<UserInfo>GetUserInfo(){...} method.
So the question is this: How to set ViewBag properties on every action when data is retrieved using async/await.
MVC is not quite fully async-friendly, particularly with filters.
You could write your own RenderAsyncAction extension method or duplicate the code in all your async actions.
Alternatively, you could attempt a bit of a hack. I describe on my blog why using Result in ASP.NET can deadlock, but there's a workaround: use ConfigureAwait(false) on every await in GetUserInfo.
Then you can define a synchronous wrapper:
public UserInfo GetUserInfoBlocking()
{
return GetUserInfo().Result;
}
You should be able to use GetUserInfoBlocking in OnActionExecuting or RenderAction.
Please note the side effects:
This approach uses multiple threads per request, so this will decrease scalability. The pure async approach uses multiple requests per thread, so it increases scalability.
Any exceptions from GetUserInfo will be wrapped in an AggregateException, so be sure your logging will capture the InnerException details or you'll get meaningless errors in your logs.
It's definitely best to use async all the way down instead of blocking like this. But sometimes MVC doesn't leave you a choice (hopefully this will change in the future).

Resources