Igor Konopko
Igor Konopko

Reputation: 764

Asp MVC and Web Api Async Controllers

I was working with Asp MVC 3, and in my application was created Async controller with some methods like:

public void ActionAsync()
{
   AsyncManager.OutstandingOperations.Increment(); 
   AsyncManager.Parameters["someResult"] = GetSomeResult();
   AsyncManager.OutstandingOperations.Decrement();
}

public JsonResult ActionCompleted(SometResultModel someResult)
{
   return Json(someResult, JsonRequestBehavior.AllowGet);
}

And now, when I'm working with MVC4 and Web Api I need to create controller with async actions like in mvc 3. At current time it's looks like:

public Task<HttpResponseMessage> PostActionAsync()
{
     return Task<HttpResponseMessage>.Factory.StartNew( () =>
           {
              var result = GetSomeResult();
              return Request.CreateResponse(HttpStatusCode.Created, result);
           });
}

Is it a good idea to make async actions in web api like this or there some better way is exist?

UPD. Also, if I will use

public async Task<HttpResponseMessage> ActionAsync()
{
   var result = await GetSomeResult();
   return Request.CreateResponse(HttpStatusCode.Created, result);
}

will this full action work in background thread? And how to make my GetSomeResult() function be awaitable? It's return that Task<HttpResponseMessage> is not awaitable.

Upvotes: 4

Views: 5586

Answers (1)

Pablo Cibraro
Pablo Cibraro

Reputation: 3959

There is a big difference with your original action in MVC 3 where you are basically releasing the client after the ActionAsync method is invoked (The client thread is released, and it has to call the ActionCompleted action afterward to get the results). If that's what you are looking for, you need to implement async code with tasks on the client side.

Your second version is to make the server code async but the client thread will still wait for a response synchronously. await GetResult will make the server thread to return to the ASP.NET thread pool until the GetResult method returns something, so that thread can be reused with another request. It does not have anything to do with background work. If you want to use a fire and forget approach, you need to use the Task.Factory.StartNew(() => your code) or ThreadPool.QueueUserWorkItem(() => your code)

Upvotes: 2

Related Questions