If you want use Polly with Refit generated clients then you can do one of the followings:
Define Policy<string>
- Let's suppose your
IClassevivaAPI
looks like this:
public interface IClassevivaAPI
{
[Get("/500")]
Task<string> Get();
}
- and the refit client registration like that:
builder.Services
.AddRefitClient(typeof(IClassevivaAPI))
.ConfigureHttpClient((_, client) => client.BaseAddress = new Uri("https://httpstat.us/"));
- Use
PolicyRegistry
to register your retry policy
var registry = new PolicyRegistry();
registry.Add("A", Policy<string>
.Handle<ApiException>(ex => { return true; }) //Predicate added to be able to add breakpoint here
.RetryAsync(2, onRetry: (_, __) => { })); //onRetry added to be able to add breakpoint here
builder.Services.AddPolicyRegistry(registry);
ExecuteAsync
to decorate your api call
private readonly IClassevivaAPI _api;
private readonly IReadOnlyPolicyRegistry<string> _registry;
public WhateverController(IClassevivaAPI api, IReadOnlyPolicyRegistry<string> registry)
{
(_api, _registry) = (api, registry);
}
[HttpGet]
public async Task Get()
{
var retry = _registry.Get<IAsyncPolicy<string>>("A");
var response = await retry.ExecuteAsync(_api.Get);
}
Define Policy<IApiResponse>
If you wish to use IApiResponse
in the policy definition then
registry.Add("B", Policy<IApiResponse>
.Handle<ApiException>(ex => { return true; }) //Predicate added to be able to add breakpoint here
.RetryAsync(2, onRetry: (_, __) => { })); //onRetry added to be able to add breakpoint here
and
var retry = _registry.Get<IAsyncPolicy<IApiResponse>>("B");
var response = await retry.ExecuteAsync(async () =>
{
var result = await _api.Get();
return new ApiResponse<string>(null, result, null);
});
Define Policy<HttpMessageResponse>
The AddPolicyHandler
anticipates a policy which implements the IAsyncPolicy<HttpResponseMessage>
. Neither A
nor B
implements it that's why you can't use the AddPolicyHandler
for that.
But, if you change the interface like this:
public interface IClassevivaAPI
{
[Get("/500")]
Task<HttpResponseMessage> Get();
}
the policy needs to updated as well
builder.Services
.AddRefitClient(typeof(IClassevivaAPI))
.ConfigureHttpClient((_, client) => client.BaseAddress = new Uri("https://httpstat.us/"))
.AddPolicyHandler(Policy<HttpResponseMessage>
.HandleResult(res => res.StatusCode == HttpStatusCode.InternalServerError)
.RetryAsync(2, onRetry: (_, __) => { })); //onRetry added to be able to add breakpoint here
and the usage
var result = await _api.Get();
Comparison of alternatives
Option |
Pros |
Cons |
Policy<string> |
You can use high-level strongly typed response and ApiException |
You can't use it via AddPolicyHandler |
Policy<IApiResponse> |
You can use low-level strongly typed response and ApiException |
You can't use it via AddPolicyHandler |
Policy<HttpMessageResponse> |
You can use AddPolicyHandler |
You can't use most of refit's advantages |