Below I am showcasing the policy I am using to handle a PostAsync() request using a HttpClient. However, it seems like even though I passed generic Exception
, it still decides to throw it and fail to retry. I would like to ask why this is, and any workarounds.
HttpsClient Setup
_httpClientHandler = new HttpClientHandler()
{
UseCookies = true,
CookieContainer = new CookieContainer(),
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
_httpClient = new HttpClient(_httpClientHandler) { Timeout = TimeSpan.FromSeconds(10) };
Post Request
private async Task PreparePayloadByDate(DateTime date)
{
// Define the retry policy with exponential backoff
var retryPolicy = Policy<HttpResponseMessage>.Handle<HttpRequestException>()
.Or<TaskCanceledException>()
.OrResult(r => !r.IsSuccessStatusCode)
.WaitAndRetryForeverAsync(
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (exception, retryCount, timeSpan) =>
{
_logger.Log(LogEnums.Error, $"Attempt {retryCount} failed. Retrying in {timeSpan} seconds...");
});
var stringPayload = JsonConvert.SerializeObject(new { key = "days", options = date.ToString("yyyy-MM-dd") });
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
var r1 = await retryPolicy.ExecuteAsync(() =>
_httpClient.PostAsync($"{_moduleConfig.Endpoint}/options/selected", httpContent));
}
I have also tried using a Policy Timeout rather than the HttpClient's Timeout. This seemed to have the same outcome. See Answer for more context
I would also like to add that this RetryPolicy is inside a try catch, and the exception being thrown is The request was canceled due to the configured HttpClient.Timeout of 15 seconds elapsing.
with a StackTrace of at System.Net.Http.HttpClient.HandleFailure(~)
.
Additional Notes (Added on 2/1/2025)
Even when the timeout of the HttpClient is set to 3 minutes, 10 minutes, etc. It always will timeout. I believe its due to the url I am posting through rate limiting but not really sure. I can not get it to replicate in a browser.
Below I am showcasing the policy I am using to handle a PostAsync() request using a HttpClient. However, it seems like even though I passed generic Exception
, it still decides to throw it and fail to retry. I would like to ask why this is, and any workarounds.
HttpsClient Setup
_httpClientHandler = new HttpClientHandler()
{
UseCookies = true,
CookieContainer = new CookieContainer(),
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
_httpClient = new HttpClient(_httpClientHandler) { Timeout = TimeSpan.FromSeconds(10) };
Post Request
private async Task PreparePayloadByDate(DateTime date)
{
// Define the retry policy with exponential backoff
var retryPolicy = Policy<HttpResponseMessage>.Handle<HttpRequestException>()
.Or<TaskCanceledException>()
.OrResult(r => !r.IsSuccessStatusCode)
.WaitAndRetryForeverAsync(
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (exception, retryCount, timeSpan) =>
{
_logger.Log(LogEnums.Error, $"Attempt {retryCount} failed. Retrying in {timeSpan} seconds...");
});
var stringPayload = JsonConvert.SerializeObject(new { key = "days", options = date.ToString("yyyy-MM-dd") });
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
var r1 = await retryPolicy.ExecuteAsync(() =>
_httpClient.PostAsync($"{_moduleConfig.Endpoint}/options/selected", httpContent));
}
I have also tried using a Policy Timeout rather than the HttpClient's Timeout. This seemed to have the same outcome. See Answer for more context
I would also like to add that this RetryPolicy is inside a try catch, and the exception being thrown is The request was canceled due to the configured HttpClient.Timeout of 15 seconds elapsing.
with a StackTrace of at System.Net.Http.HttpClient.HandleFailure(~)
.
Additional Notes (Added on 2/1/2025)
Even when the timeout of the HttpClient is set to 3 minutes, 10 minutes, etc. It always will timeout. I believe its due to the url I am posting through rate limiting but not really sure. I can not get it to replicate in a browser.
Share Improve this question edited Feb 1 at 20:37 VoidSharp asked Feb 1 at 4:34 VoidSharpVoidSharp 335 bronze badges 4 |1 Answer
Reset to default 1TBH was not able to repro the issue, for me your code catches the timeout, but in general your code is not shielded from the exceptions since r2.EnsureSuccessStatusCode();
will throw for non-successes. In general you might want to handle results too in your policy. For example (for testing purposes):
var retryPolicy = Policy<HttpResponseMessage>
.Handle<Exception>()
.OrResult(r => !r.IsSuccessStatusCode)
.WaitAndRetryForeverAsync(
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (exceptionOrResult, timeSpan) => ...);
Also you can use Microsoft.Extensions.Http.Polly
which has some default setup and convenient methods:
var policy = HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2,
retryAttempt)));
See the Implement HTTP call retries with exponential backoff with IHttpClientFactory and Polly policies doc.
TaskCanceledException
. After giving my project a few minutes, I will mark a answer to close this question. Thank you everyone who helped me come to this conclusion – VoidSharp Commented Feb 1 at 21:04