Polly with .NET 6, Part 8 - Policy Registry with Minimal APIs, and HttpClientFactory
Want to learn more about Polly? Check out my Pluralsight course on it.
The Polly Policy Registry lets you register policies in a central location, and then retrieve them by name. This is useful when you have many policies. It also makes it to reuse policies throughout your application.
The Policy Registry can also be used with the HttpClientFactory
to apply policies to HTTP requests made by the HttpClient
. Depending on the HTTP method of the request, you can apply different policies.
In the example below, you will use a Wait and Retry Policy for GET
requests, and a Retry Policy for DELETE
requests. A No-Op Policy is used for all other requests.
Create a new Web API application and add the Microsoft.Extensions.Http.Polly
NuGet package. That will bring in all the other dependencies you need.
Replace Program.cs
with the following code -
1using Polly;
2using Polly.Registry;
3
4var builder = WebApplication.CreateBuilder(args);
5
6IPolicyRegistry<string> registry = builder.Services.AddPolicyRegistry();
7
8IAsyncPolicy<HttpResponseMessage> waitAndRetryPolicy =
9 Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
10 .WaitAndRetryAsync(3,
11 retryAttempt => TimeSpan.FromSeconds(retryAttempt));
12
13IAsyncPolicy<HttpResponseMessage> simpleRetryPolicy =
14 Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
15 .RetryAsync(3);
16
17IAsyncPolicy<HttpResponseMessage> noOpPolicy = Policy.NoOpAsync()
18 .AsAsyncPolicy<HttpResponseMessage>();
19
20registry.Add("WaitAndRetryPolicy", waitAndRetryPolicy);
21registry.Add("SimpleRetryPolicy", simpleRetryPolicy);
22registry.Add("NoOpPolicy", noOpPolicy);
23
24builder.Services.AddHttpClient("jsonplaceholder", client =>
25{
26 client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
27 client.DefaultRequestHeaders.Add("Accept", "application/json");
28}).AddPolicyHandlerFromRegistry((policyRegistry, httpRequestMessage) =>
29{
30 if (httpRequestMessage.Method == HttpMethod.Get)
31 {
32 return policyRegistry.Get<IAsyncPolicy<HttpResponseMessage>>("WaitAndRetryPolicy");
33 }
34 else if (httpRequestMessage.Method == HttpMethod.Delete)
35 {
36 return policyRegistry.Get<IAsyncPolicy<HttpResponseMessage>>("SimpleRetryPolicy");
37 }
38 return policyRegistry.Get<IAsyncPolicy<HttpResponseMessage>>("NoOpPolicy"); // for other HTTP methods
39});
40
41var app = builder.Build();
42
43app.MapGet("/ToDos/{id}", async (int id, IHttpClientFactory httpClientFactory) =>
44{
45 var httpClient = httpClientFactory.CreateClient("jsonplaceholder");
46 string requestEndpoint = $"ToDos/{id}";
47
48 // this request will be up retried 3 times using the WaitAndRetryPolicy
49 HttpResponseMessage response =
50 await httpClient.GetAsync(requestEndpoint);
51
52 if (response.IsSuccessStatusCode)
53 {
54 var todo = await response.Content.ReadFromJsonAsync<ToDo>();
55 return Results.Ok(todo);
56 }
57 return Results.Problem("Something went calling the ToDo");
58});
59
60app.MapDelete("/ToDos/{id}", async (int id, IHttpClientFactory httpClientFactory) =>
61{
62 var httpClient = httpClientFactory.CreateClient("jsonplaceholder");
63 string requestEndpoint = $"ToDos/{id}";
64
65 // this request will be up retried 3 times using the SimpleRetryPolicy
66 HttpResponseMessage response =
67 await httpClient.DeleteAsync(requestEndpoint);
68
69 if (response.IsSuccessStatusCode)
70 {
71 return Results.Ok();
72 }
73 return Results.Problem("Something went deleting the ToDo");
74});
75
76app.Run();
77
78public class ToDo
79{
80 public int UserId { get; set; }
81 public int Id { get; set; }
82 public string Title { get; set; }
83 public bool Completed { get; set; }
84}
- Line 6 creates a Polly registry.
- Lines 8-11 create a Wait and Retry Policy that retries up to three times.
- Lined 13-15 create a Retry Policy that retries up to three times.
- Lines 17-18 create the No-Op Policy, this is used when no other policy applies, it is a simple pass-through.
- Lines 20-22 add the above policies to the Policy Registry.
- Lines 24-28 create a
HttpClientFactory
, passing it a policy a selector Func. - Lines 29-39 logic to choose the appropriate policy based on the HTTP method.
- Lines 43-58 create an endpoint that takes
HttpClientFactory
as a parameter, creates aHttpClient
, and makes a GET request using the Wait and Retry Policy. - Lines 60-74 create an endpoint that takes
HttpClientFactory
as a parameter, creates aHttpClient
, and makes a DELETE request using the Retry Policy.