Two years ago, in an ASP.NET Core 8 MVC web app, I used HttpClient to make HTTP requests to an API, like this:
HttpClientHandler httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential(configuration[Id], configuration[Pwd])
};
using var client = new HttpClient(httpClientHandler);
client.DefaultRequestHeaders.Add("Accept", "application/xml");
var result = client.GetAsync($"{configuration[Host]}/api/example").Result;
I know this is not the recommended way to use HttpClient but I needed to set the basic authentication credentials and the API's base address (host) dynamically so I couldn't register a static HttpClient with the DI container of the app; doing so seemed to be extremely complicated because the Host, Id, and Pwd settings exist both in appsettings.json and appsettings.Development.json and are user-profile based, for example:
"API": {
"Debug": {
"Host": "...",
"Id": "...",
"Pwd": "..."
},
"Production": {
"Host": "...",
"PartnerId": "...",
"Pwd": "..."
}
}
where "Debug" and "Production" are two profiles and the actual profile is based on the logged-in user and therefore it's determined at runtime.
For two years the above code worked fine until yesterday when all requests started to fail with response:
<?xml version="1.0" encoding="UTF-8"?>
<error>
<message context="ForbiddenException">Forbidden resource</message>
</error>
Of course, at first, I suspected that something has changed on the API side. Nevertheless, sending the same requests from Postman worked fine! Replacing HttpClient with HttpWebRequest worked fine, too!
Anyone knows how can I discover what is suddenly wrong with the HttpClient requests?
HttpClientworks fine, probably the server got unhappy with what you were sending it. Almost certainly a missing/incorrect header. Use a transparent proxy such as Fiddler to compare working and non-working response to see what the difference is. Also don't ever use.Resultusevar result = await client.GetAsync($"{configuration[Host]}/api/example");insteadAddHttpClientas several of the overloads passIServiceProvideras a parameter.NetworkCredentialis used for multiple authentication types, including NTLM, Basic, Kerberos. The NetworkCredentials documentation adds the credential to a CredentialCache with an explicit authentication type. Perhaps the code was using NTLM until now and the server disabled it?