C# – Calling async method in controller

asp.net-mvc-4async-awaitc

I have a controller with something like the following:

public MyController : Controller
{
    public ActionResult DoSomething()
    {
        CallSomeMethodWhichDoesAsyncOperations();
        return Json(new { success = successful }, JsonRequestBehavior.AllowGet);
    }
}

When calling my controller I get the following error:

An asynchronous operation cannot be started at this time. Asynchronous operations
may only be started within an asynchronous handler or module or during certain
events in the Page lifecycle. If this exception occurred while executing a Page,
ensure that the Page is marked <%@ Page Async="true" %>.

Now I dont have control over CallSomeMethodWhichDoesAsyncOperations and the method itself is not async but internally does some async fire and forget. What can I do to fix it? Have tried to change the controller to an AsyncController and/or making the method in the controller async.

Edit:

When I attempted to use an AsyncController I first tried, with the same result

public MyController : AsyncController
{
    public ActionResult DoSomething()
    {
        CallSomeMethodWhichDoesAsyncOperations();
        return Json(new { success = successful }, JsonRequestBehavior.AllowGet);
    }
}

And then

public MyController : AsyncController
{
    public async Task<ActionResult> DoSomething()
    {
        CallSomeMethodWhichDoesAsyncOperations();
        return Json(new { success = successful }, JsonRequestBehavior.AllowGet);
    }
}

Which did change the exception to the following "An asynchronous module or handler completed while an asynchronous operation was still pending."

Best Answer

Now I dont have control over CallSomeMethodWhichDoesAsyncOperations and the method itself is not async but internally does some async fire and forget. What can I do to fix it?

Contact the person who wrote it and make them fix it.

Seriously, that's the best option. There's no good fix for this - only a hack.

You can hack it to work like this:

public MyController : Controller
{
  public async Task<ActionResult> DoSomething()
  {
    await Task.Run(() => CallSomeMethodWhichDoesAsyncOperations());
    return Json(new { success = successful }, JsonRequestBehavior.AllowGet);
  }
}

This is not recommended. This solution pushes off work to a background thread, so when the async operations resume, they will not have an HttpContext, etc. This solution completes the request while there is still processing to be done. This solution will not behave correctly if the server is stopped/recycled at just the wrong time.

There is only one proper solution: change CallSomeMethodWhichDoesAsyncOperations.