1

How can I make repetitive calls to a URL by time intervals till I get successful result or timeout?

I upload a file to an API and it sends me a URL to let me check if my file is processed successfully. I want to make it so this url is checked in the server until the pending status is changed. There are successful, failed and pending statuses. I want to keep the user wait until the result is either fail or success.

[HttpGet]
public async Task<ActionResult> Get()
{
    ...
    response = await client.GetAsync(other_api_url);

    if(response.IsSuccessStatusCode)
    {
        string result = response.Content.ReadAsStringAsync().Result;
        dynamic output = JsonConvert.DeserializeObject<dynamic>(result);

        statusUrl = output.url_to_check_status;

        //make a call to statusUrl check if content is ready
        //get result and parse it
        ...

        status = output.status;

        if(status == "SUCCESS")
        {
            //good path
            return Ok();
        }
        else
        {
            //make another call after n seconds to check again
        }
    }

    return NotFound();
}
5
  • call the same function recursively until the successful response Commented Oct 5, 2018 at 13:15
  • Processing might take up to 10 seconds, so that is not a good idea. Commented Oct 5, 2018 at 13:18
  • repetitive calls to a URL till I get successful result or timeout?? - But this is what you're asking?? Commented Oct 5, 2018 at 13:19
  • 1
    mixing async-await with blocking .Result risks deadlocks Commented Oct 5, 2018 at 13:29
  • One approach would be to handle it outside of the code you have posted here. Put the behaviour to handle the pending status code by retrying periodically into a DelegatingHandler. You can add that to the message handling "stack" at the point where you create the HttpClient instance. Commented Oct 5, 2018 at 13:40

2 Answers 2

2

You can use a loop with Task.Delay, like this:

bool done = false;
while (!done)
{
    await Task.Delay(1000);
    done = await GetStatusFromServerAsync();
}

Although you might want a timeout:

async Task<bool> CheckForCompletion(int timeoutms)
{
    var timer = StopWatch.StartNew();
    while (timer.ElapsedMilliseconds < timeoutms)
    {
        var ok = await GetStatusFromServerAsync();
        if (ok) return true;
        await Task.Yield(1000);
    }
    return false;
}
Sign up to request clarification or add additional context in comments.

Comments

2

Not that I'd agree to doing this (you should never block your request this way), but I think this should solve your problem:

[HttpGet]
public async Task<ActionResult> Get()
{
    response = await client.GetAsync(other_api_url);

    if(response.IsSuccessStatusCode)
    {
        // DO NOT USE `.Result` within async method.
        string result = await response.Content.ReadAsStringAsync();
        dynamic output = JsonConvert.DeserializeObject<dynamic>(result);

        statusUrl = output.url_to_check_status;

        bool? result = null;
        while(result == null) result = await CheckIfSuccessfulAsync(statusUrl);

        if (result) return Ok();       
        return NotFound();
    }
}

// Does not *need* to be a separate method, it's just for better readability...
private async Task<bool?> CheckIfSuccessfulAsync(string statusUrl)
{    
    //make a call to statusUrl check if content is ready
    //get result and parse it
    ...

    status = output.status;

    if (status == "SUCCESS") return true;
    else if (status == "PENDING") return false;

    return null;
}

1 Comment

Thank you for the response, this partially does the job but I get authentication error even though I provide the same credentials for the first call. works on postman not in asp.net

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.