aghaux
aghaux

Reputation: 749

how to wait for async results in second async call in asp web api

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

Answers (2)

user6996876
user6996876

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

Igor
Igor

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

Related Questions