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 inDoSomethingAsync
- when I step overExecuteAsync
DoSomethingAsync
is not called and control is returned to the function that calledMakeGetRequestAsync
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..
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!
I'm replying to this old question just to point out the Polly wiki page where this pattern was official documented:
retry-to-refresh-authorization
In particular this is the code snippet suggested:
var authorisationEnsuringPolicy = Policy
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized)
.RetryAsync(
retryCount: 1, // Consider how many retries. If auth lapses and you have valid credentials, one should be enough; too many tries can cause some auth systems to blacklist.
onRetryAsync: async (outcome, retryNumber, context) => FooRefreshAuthorizationAsync(context),
/* more configuration */);
var response = authorisationEnsuringPolicy.ExecuteAsync(context => DoSomethingThatRequiresAuthorization(context), cancellationToken);
The
FooRefreshAuthorizationAsync(...)
method can obtain a new authorization token and pass it to the delegate executed through the policy usingPolly.Context
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With