Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling async method in controller

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."

like image 925
Christian Avatar asked Sep 08 '25 14:09

Christian


1 Answers

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.

like image 71
Stephen Cleary Avatar answered Sep 10 '25 05:09

Stephen Cleary