0

I've a flow: WebApi > ServiceFramework > DBLayer > MongoDB.

Since its a new application, I ensured to have async from the ground up in all layers. However, when my DB Layer has async code, webapi never gets a response back.

API CONTROLLER

[HttpGet]
public IHttpActionResult GetAllRecords()
{
   var result = FrameworkApi.GetRecords().Result;
   return Ok(result);
}

above calls > FRAMEWORK API

public async Task<List<Record>> GetRecords()
{
    return await FrameworkDbApi.GetRecords();
}

above calls > DB FRAMEWORK API (which Calls MongoDB)

public async Task<List<Record>> GetRecords()
{
    return await Task.Run(() =>                
       NoSqlDocumentClient.GetDefaultDatabase().Result.
       GetCollection<Record>("record").AsQueryable().ToList());            

      //following Synchronous version works..but defeats the purpose  
      //return NoSqlDocumentClient.GetDefaultDatabase().Result
      //       .GetCollection<Record>("record").AsQueryable().ToList();
}

However, when the operations in either DBLayer or Framework are invoked via test case, I do get result. But when invoked via WebApi controller, the asynchronous version never returns a response while synchronous version works fine.

1 Answer 1

3

But when invoked via WebApi controller, the asynchronous version never returns a response while synchronous version works fine.

That's because your actual request is deadlocking. When you invoke the method via WebAPI, which has a SynchronizationContext, you're seeing the deadlock, in contrary to your test which hasn't got one, when the test runs fine. This is the reason why you shouldn't block on async code.

Your call-chain should look like this in order to avoid deadlocking (this is what it means to go "async all the way":

[HttpGet]
public async Task<IHttpActionResult> GetAllRecordsAsync()
{
   var result = await FrameworkApi.GetRecordsAsync();
   return Ok(result);
}

public Task<List<Record>> GetRecordsAsync()
{
    return FrameworkDbApi.GetRecordsAsync();
}

public async Task<List<Record>> GetRecordsAsync()
{
    var result = await NoSqlDocumentClient.GetDefaultDatabase();
    return result.GetCollection<Record>("record").AsQueryable().ToList();          
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.