I have a http's device that the application contact.
In first step, I have build around the IHttpFactory as preconised by Microsoft
builder.Services.AddHttpClient<ISynchronicProvider, SynchronicProvider>(client =>
{
client.BaseAddress = new Uri($"{builder.Configuration["Synchronic:protocol"]}://{builder.Configuration["Synchronic:host"]}:{builder.Configuration["Synchronic:port"]}");
client.SetBasicAuthentication(builder.Configuration["Synchronic:user"], builder.Configuration["Synchronic:pass"]);
});
This is working well, extensible with Polly and Logger and used with simple function
public async Task SendOpenP1Async() => await httpClient.GetAsync($"?E={telecommande.Emetteur}&T={telecommande.OpenP1}");
In next step, I have implemented health monitoring on this device like this
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
using var httpClient = _httpClientFactory.CreateClient();
httpClient.SetBasicAuthentication(synchronic.User, synchronic.Pass);
var response = await httpClient.GetAsync($"{synchronic.Protocol}://{synchronic.Host}:{synchronic.Port}?E={telecommande.Emetteur}&T={telecommande.Status}", cancellationToken);
return response.IsSuccessStatusCode ?
HealthCheckResult.Healthy($"Synchronic device is healthly") :
HealthCheckResult.Unhealthy("Synchronic device is unhealthy");
}
and add the feature on Program.cs by this way
builder.Services.AddHealthChecks()
.AddCheck<SynchronicHealthCheck>("Synchronic Health Check", failureStatus: HealthStatus.Unhealthy);
this is working like a charm
BUT
if I declare interfaces on same class like this
public class SynchronicProvider : ISynchronicProvider, IHealthCheck
and implement with injected HttpClient instead IHttpClientFactory
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
var response = await httpClient.GetAsync($"?E={telecommande.Emetteur}&T={telecommande.Status}", cancellationToken);
return response.IsSuccessStatusCode ?
HealthCheckResult.Healthy($"Synchronic device is healthly") :
HealthCheckResult.Unhealthy("Synchronic device is unhealthy");
}
httpClient base url is empty for this method, but ever populated on another methods.
In Program.cs, I have tried to declare health feature before and after
// Http factory
builder.Services.AddHttpClient<ISynchronicProvider, SynchronicProvider>(client =>
{
client.BaseAddress = new Uri($"{builder.Configuration["Synchronic:protocol"]}://{builder.Configuration["Synchronic:host"]}:{builder.Configuration["Synchronic:port"]}");
client.SetBasicAuthentication(builder.Configuration["Synchronic:user"], builder.Configuration["Synchronic:pass"]);
});
// Health check
builder.Services.AddHealthChecks()
.AddCheck<SynchronicProvider>("Synchronic Health Check", failureStatus: HealthStatus.Unhealthy);
So, why it is not working ? I guess that dependancy injection from AddHttpClient that "take the lead", but I don't know not more.
Can you explain this, and / or resolve the issue ?
Thanks for helping
In response of this use case, you can inherit interface IHealthCheck
on IProvider
and declare IProvider
for HealthCheck binding.
Then, in implementation class, you have the both implementation and especially a well configured HttpClient.
//interface declaration
public interface ISynchronicProvider : IHealthCheck { ... }
// binding HealthCheck on interface
builder.Services.AddHealthChecks()
.AddCheck<ISynchronicProvider>("Synchronic Health Check", failureStatus: HealthStatus.Unhealthy);
// httpClient is working in both impl.
public async Task SendStatusAsync() => await httpClient.GetAsync($"?E={telecommande.Emetteur}&T={telecommande.Status}");
// https://stackoverflow.com/questions/78794475/build-a-typed-httpclient-with-addhealthcheck-on-same-class
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
var response = await httpClient.GetAsync($"?E={telecommande.Emetteur}&T={telecommande.Status}", cancellationToken);
return response.IsSuccessStatusCode ?
HealthCheckResult.Healthy($"Synchronic device is healthly") :
HealthCheckResult.Unhealthy("Synchronic device is unhealthy");
}