0

I try to use Polly with HttpClient request.

This is my code:

    public static  async Task<ResponseWs> callAsync(int IdHeader)
    {
        ResponseWs w = new ResponseWs();
        w.retCode = 1;
        w.Message = "Errore Generico";

        httpcli = new HttpClient();
        ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

        getInbound(IdHeader, out int i, out string jsonObject, out string orderNum);
        url = String.Format(ConfigurationManager.AppSettings["XXXUrl"].ToString() + "charge?orderNum=" + orderNum);
        httpcli.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ConfigurationManager.AppSettings["XXXAuth"].ToString());
        httpcli.DefaultRequestHeaders.ConnectionClose = true;
        Logger.WriteInfo(url);
        Logger.WriteInfo(jsonObject);


        var retryPolicy = Policy
                .Handle<HttpRequestException>()
                .OrResult<HttpResponseMessage>(r => r.StatusCode != HttpStatusCode.OK)
                .WaitAndRetryAsync(maxRetryAttempts,  j=> pauseBetweenFailures, (result, timeSpan, retryCount, context) => {
                                Logger.WriteInfo($"Request failed with {result.Result.StatusCode}. Retry count = {retryCount}. Waiting {timeSpan} before next retry. ");
                            });

        try
        {
            var response = await retryPolicy.ExecuteAsync(async () =>
            {
                var cont = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
                var post = await httpcli.PostAsync("https://httpbin.org/status/400", cont).ConfigureAwait(false);
                return post;
            });

            if (response.IsSuccessStatusCode)
            {
                string responseContent = response.Content.ReadAsStringAsync().Result;

                XXXError sperr = JsonConvert.DeserializeObject<XXXError>(responseContent);

                if (sperr.status.ToUpper() == "OK")
                {
                    Logger.WriteInfo("OK");
                    w.retCode = 0;
                    w.Message = "OK";
                    return w;
                }
                else
                {
                    Logger.WriteError(responseContent);
                    Logger.WriteError(sperr.message);
                    w.retCode = 2;
                    w.Message = sperr.message;
                    return w;
                }
            }
            else
            {

                Logger.WriteError("Errore: " + response.StatusCode);
                Logger.WriteError(response.Content.ToString());
                w.retCode = 1;
                w.Message = "Errore Chiamata MW";
                return w;
            }
        }
        catch (AggregateException e)
        {
            foreach (Exception ie in e.InnerExceptions)
            {
                Logger.WriteError(ie.GetType().Name + ":" + ie.Message);
                Logger.WriteError(e.InnerException.Message);
            }
            w.retCode = 1;
            w.Message = "Errore Chiamata MW";
            return w;
        }
        catch (HttpRequestException e)
        {
            Logger.WriteError(e.Message);
            Logger.WriteError(e.InnerException.Message);
            w.retCode = 1;
            w.Message = "Errore Chiamata MW";
            return w;
        }
        catch (Exception ex)
        {
            Logger.WriteError(ex.Message);
            Logger.WriteError(ex.InnerException.Message);
            w.retCode = 1;
            w.Message = "Errore Chiamata MW";
            return w;
        }
    }

My log reports:

Request failed with BadRequest. Retry count = 3. Waiting 00:00:10 before next retry. 
Request failed with BadRequest. Retry count = 2. Waiting 00:00:10 before next retry. 
Request failed with BadRequest. Retry count = 1. Waiting 00:00:10 before next retry.

but the request remains pending, and I have to manually force close.

Where is the problem?

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • 1
    `post.Wait();` ? That's always a bug in an async method. Besides, that's the *result* of the call, not the call itself. Your code isn't awaiting and retrying the async call, it's "awaiting" the exact same result – Panagiotis Kanavos Nov 09 '21 at 14:22
  • @DottorCryDottorCry Do you still have the same problem after making the modification suggested by Panagiotis? – Peter Csala Nov 10 '21 at 14:39

1 Answers1

0

The code is awaiting the result of the single HTTP call made by httpClient.PostAsync("https://httpbin.org/status/400", null);, not the call itself. As a result, it retries reading that result, not retrying the call. If post.Wait(); throws the code will keep retrying and rethrowing the same exception.

The code to retry should be inside the retryPolicy.ExecuteAsync call:

 var response = await retryPolicy.ExecuteAsync(async () =>
    {
        var res=await httpClient.PostAsync("https://httpbin.org/status/400", null);
        return res;
    });

or even :

var response = await retryPolicy.ExecuteAsync(()=> 
                          httpClient.PostAsync("https://httpbin.org/status/400",
                          null));

Using the question's code that would be:

var response = await retryPolicy.ExecuteAsync(async ()=> {

    var cont = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
    var post = await httpcli.PostAsync(url, cont);
    return post;
});
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236