There is a lot of HttpClient Errors is caused by server overload, temporary network timeouts and generic gliches in the the downstream systems. Those error are temporary and can be dealt with using a retry pattern. In .NET Core, the most common retry library is the Polly library.
Step 1. Download the nuget packages
Microsoft.Extensions.Http.Polly
Polly.Extensions.Http
Step 2. CONFIGURE SERVICES IN STARTUP.CS
IOption is used for strongly typed configuration. We need to download the nuget package Microsoft.Extensions.Options for IOption. We need a class structure that matches with the configuration.
So create a class HttpSettingsOptions as below
{
public const string HttpSettings = "HttpSettings";
public int RetryCount { get; set; }
public int InitialRetryDelay { get; set; }
}
Create the similar structure in appSetting.json
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"HttpSettings": {
"RetryCount": 3,
"InitialRetryDelay": 2
},
"ServiceURL": {
"Questionnaire": "https://localhost:44368/api"
}
}
Create a method GetRetryPolicy in startup.cs and which accept the above httpsetting
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(options.RetryCount, retryAttempt =>
{
return TimeSpan.FromSeconds(Math.Pow(options.InitialRetryDelay, retryAttempt));
});
}
}
Now for the parameter of AddHttpClient methods (i.eHttpClientWithBackOff) create a below class
public class HttpClientConstants
{
public const string HttpClientWithBackOff = "HttpClientBackOff";
}
Step 3: USE THE IHttpClientFactory IN THE CALLING CLASS
The IHttpClientFactory can be injected using constructor injection. The cool part of the Polly implementation is that your HttpClient code does not contain any special retry-code, just the usual Get or Post calls:
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ServiceURLOptions _serviceUrlOptions;
public QuestionnaireQueryService(IOptions<ServiceURLOptions>
serviceUrlOptions,
IHttpClientFactory httpClientFactory)
{
_serviceUrlOptions = serviceUrlOptions != null
? serviceUrlOptions.Value
: throw new ArgumentNullException($"Options/Configuration not found for {nameof(serviceUrlOptions)}");
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
}
public async Task<QuestionnaireServiceModel> GetAllQuestionnaire()
{
QuestionnaireServiceModel questionnaireServiceModel = null;
using var httpClient = _httpClientFactory.CreateClient(HttpClientConstants.HttpClientWithBackOff);
//httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + Token);
var questionnaireResponse = await httpClient.GetAsync($"{_serviceUrlOptions.Questionnaire}/Questions");
var qResponse = await questionnaireResponse.Content.ReadAsStringAsync();
if (questionnaireResponse.IsSuccessStatusCode)
{
questionnaireServiceModel = JsonConvert.DeserializeObject<QuestionnaireServiceModel>(qResponse);
}
return questionnaireServiceModel;
}
}
No comments:
Post a Comment