Reputation: 749
I have to use the results in first async call to call the second async method but web api returns empty results before it finish calling method 2?
I have tryed using .ContinueWith but that appears in a deadlock
Could someone lead me to some kind of a solution?
example:
public class AsyncApiController : ApiController
{
[ActionName("GetClientBySSN")]
public async Task<IHttpActionResult> GetClientBySSN(string ssn)
{
return Ok(await _repository.GetClientBySSN(ssn));
}
}
public interface IResRepository
{
Task<ClientResponse> GetClientBySSN(string ssn);
}
public class ResRepository : IResRepository
{
public Task<ClientResponse> GetClientBySSN(string ssn)
{
//async method
Task task1 = _service.GetClientNumberBySSN(ssn);
int clientNumber = task1.Result.clientnumber;
if (clientNumber != null)
{
//another async method that uses ID from the first result
return _service.GetClientDetailsByClientNumber(clientNumber);
}
else
{
return null;
}
}
}
Upvotes: 2
Views: 2217
Reputation:
If you are on a web api or more generally on a network application service, please distinguish between client and server side.
First of all you don't need an async api to make your client async: both sides are completely independent. So, my initial suggestion is that you may want to make only the client async and to maintain the web api as synchronous call on the server (of course there can be an application host framework that is responsible to instanciate the calls, load balancing, etc.).
A second point is related to the impact of an asynchronous api, meaning that the client infrastructure is supposed to be notified of the request completion, so there is a channel to receive such a notification that must be opened on the client side and that could not be completely obvious during the design of this interface. So again I would go for a client only async version of the interface, unless there are clear, different architectural requirements.
A final note, back to your question, in case you just fixed your code with the classical async - await all the way...
99% of the time, await Foo() should be await Foo().ConfigureAwait(false)
And your case seems to fall in a context free situation
Upvotes: 0
Reputation: 62213
You needed to add async
to your method signature and then add the await
keyword in your method calls in your method.
I marked the places where you needed to change your code as well as a spot where the code did not make much sense like checking if an int
instance was null
(your if statement).
public class ResRepository : IResRepository
{
// missing async
public async Task<ClientResponse> GetClientBySSN(string ssn)
{
// missing await - also use await and get result directly instead of getting the task and then awaiting it
var client = await _service.GetClientNumberBySSN(ssn);
// type int can never be null, this will never eval to false. maybe you meant int? above
// I changed to to client null check instead, maybe that is what you were going for
if (client != null)
{
//another async method that uses ID from the first result
// change - missing await
return await _service.GetClientDetailsByClientNumber(client.clientNumber);
}
else
{
return null;
}
}
}
Also it is good practice to name your methods that make use of await/async with the suffix Async
. So GetClientDetailsByClientNumber
would become GetClientDetailsByClientNumberAsync
and GetClientBySSN
would become GetClientBySSNAsync
. This makes that implementation detail of the code clearer to the caller.
Upvotes: 3