-1

I set up the following service collection with a Refit client and a Polly policy for dependency injection in my UWP app:

var serviceCollection = new ServiceCollection();

serviceCollection
    .AddRefitClient(typeof(IClassevivaAPI))
    .ConfigureHttpClient(
        (sp, client) =>
        {
            client.BaseAddress = new Uri(Endpoint.CurrentEndpoint);
        }
    )
    .AddPolicyHandler(
        Policy<HttpResponseMessage>
            .HandleResult(r => r.StatusCode == System.Net.HttpStatusCode.Unauthorized)
            .RetryAsync(
                1,
                async (ex, count) =>
                {
                    Debug.WriteLine("Retry {0} times", count);

                    var loginCredentials = new CredUtils().GetCredentialFromLocker();

                    if (loginCredentials != null)
                    {
        //the retry can continue
                    }
                }
            )
    );           

When the StatusCode of the http response is 401 (which in the API I'm using means that the session has expired) the app checks whether credentials have been stored in my app (in my app at the login stage I can choose if this is a temporary session without saving the credentials) or not.

If credentials are stored the Polly policy can continue retrying the request.

But I want that in case of credentials not stored the policy doesn't execute the retry but instead closes the app.

Is there a way to tell the Polly policy to execute the retry conditionally when handling that specific http event without hacky tricks?

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Gabboxl
  • 91
  • 3
  • 16

1 Answers1

0

Since the HandleResult can accept a synchronous delegate which returns true or false (Func<T, bool>) that's why you can combine your status code and credential check

Policy<HttpResponseMessage>
    .HandleResult(r => 
       r.StatusCode == HttpStatusCode.Unauthorized
       && new CredUtils().GetCredentialFromLocker() != null)
    .RetryAsync(1, (_, count) => Debug.WriteLine("Retry {0} times", count));               

UPDATE #1

But how can I execute code within the policy (to close the app in my case) in case the credential check is null?

Since you have applied the retry logic against the entire HttpClient (as a DelegatingHandler under the hood) that's why you should not try to exit the app from the policy.

A better approach could be to throw a custom exception either from the policy or from the GetCredentialFromLocker and wrap your refit client call with a try-catch to handle that exception by exiting application.

If you would add the retry policy into the PolicyRegistry (rather than on the HttpClient) then you would have another option as well. The ExecuteAsync can receive a Context object which you can manipulate inside the policy. So, if the GetCredentialFromLocker method call returns null then you set a "flag" on the context. After the ExecuteAsync call you can assess the context and exit the application if needed.

Peter Csala
  • 17,736
  • 16
  • 35
  • 75