Currenty I building a solution which is basically an integration between multiple external REST services. Since the solution is having multiple external service, I want to use the .NET ClientFactory to create HttpClients whenever they are wanted. Unfortunately an HttpClient instance created from the ClientFactory always results in an Unauthorized. This is a bit strange since directly creating a new HttpClient results in a success. I red the Microsoft documentation about the HttpClientFactory to determine the differences and possible use cases.
I compared the two different HttpClient instances by extracting the entire objects and did a meld comparison without any differences. Also with postman the call to the service succeeds.
The code which extracts and creates the HttpClient instance (which fails) looks like this:
Programm.cs
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
services.AddHttpClient("ClientName", client =>
{
client.BaseAddress = new Uri("https://my.domain.com");
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("username:password"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
// Set the content type header
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
});
TicketRepository.cs
public class TicketsRepository(
IHttpClientFactory _httpClientFactory) : ITicketsRepository
{
private readonly HttpClient _httpClient = _httpClientFactory.CreateClient("ClientName");
public async Task<Tickets> GetTicketByNumber(
int ticket,
CancellationToken cancellationToken)
{
// HttpContent content = new StringContent(string.Empty);
HttpResponseMessage response = await _httpClient.GetAsync(
$"{Constants.TicketsUrlTemplate}/{ticket}",
cancellationToken);
if (!response.IsSuccessStatusCode)
{
//_logger.LogError("Could not successfully retrieve data. Invalid response data is: {response}", response.ToString());
throw new HttpRequestException($"PhpServer dit not respond with an http response status 200: {response}");
}
return new Tickets();
}
}
The code which creates an HttpClient instance on every method call and succeeds extracting data looks like this:
public async Task GetTicketByNumber(
int ticket,
CancellationToken cancellationToken)
{
using (HttpClient client = new HttpClient())
{
Set the base address
client.BaseAddress = new Uri("https://my.domain.com");
Set the basic authentication header
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("username:password"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
Set the content type header
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
Make the GET request
HttpResponseMessage response = await client.GetAsync($"/urlTemplate/{ticket}/", cancellationToken);
Check for success
response.EnsureSuccessStatusCode();
Read and log the response content
string responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine("Response Content: " + responseContent);
}
catch (HttpRequestException e)
{
Console.WriteLine("Request error: " + e.Message);
}
}
}
I did a blank comparison with the Response Objects and HttpClient Objects with identical headers, version, host etc… I must have overlooked something stupid since the ClientFactory works for other Rest Services configured on startup. It is hard to monitor stuf on the server side, since I do not have any physical acccess towards that REST Service, nor do I have access to the source of it. Hopefully someone can point me in the right direction.