Using Polly to retry after HttpStatusCode.Unauthorized

Vinyl Warmth picture Vinyl Warmth · Jan 28, 2017 · Viewed 9.6k times · Source

I'm making calls to an external API and want to deal with the event that a call returns an Unauthorized HttpResponseMessage. When this happens I want to refresh the access token and make the call again.

I'm trying to use Polly with the following code:

    public async Task<HttpResponseMessage> MakeGetRequestAsync()
    {
        var retryPolicy = Policy
            .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized)
            .Retry(1, (exception, retryCount) =>
            {
                RefreshAccessToken();
            });

        var result = await retryPolicy.ExecuteAsync(() => CallApiAsync());

        return result;
    }


    private async Task<HttpResponseMessage> CallApiAsync()
    {
        var url = Options.ResourceSandboxUrl;

        var httpClient = new HttpClient();
        SetRequestHeaders(httpClient);
        var response = await httpClient.GetAsync(url);

        response.StatusCode = HttpStatusCode.Unauthorized;
        return response;
    }

I put breakpoints on the ExecuteAsync statement and in DoSomethingAsync - when I step over ExecuteAsync DoSomethingAsync is not called and control is returned to the function that called MakeGetRequestAsync

I don't understand why DoSomethingAsync is not called - can anyone help me with what I'm trying to achieve?

I've looked at the Polly documentation & Polly questions on Stack Overflow but I can't figure out what's going on..

Answer

mountain traveller picture mountain traveller · Jan 28, 2017

To use ExecuteAsync() you must declare the policy as .RetryAsync(...), not .Retry(...).

If your actual code reads exactly as the code sample above, the .ExecuteAsync(...) will be throwing for the mismatch between .Retry(...) [a sync policy] and .ExecuteAsync(...) [an async execution]. Since this exception is thrown, CallApiAsync() is indeed never invoked. You should be able to see the thrown exception, when calling MakeGetRequestAsync()

Overall code approach looks good tho: this retry-refreshing-authentication is a proven pattern with Polly!