Reputation: 1654
I have a .NET Core 3.0 Console application (although I plan to change this to a Blazor app later on).
In my Program class's public static void Main
method, I am configuring dependency injection using the pattern described by Microsoft here.
In particular, I want to register a handful of HttpClient
instances using the "named clients" pattern described here.
It's all fine except for this one problem: My second and third HttpClient
instances should have a DefaultRequestHeader
that passes a session Id. But I won't know the value of the session Id until I execute an API command to log in to a remote server using the first HttpClient
instance. What should I do?
My code so far is below.
Can I somehow get a reference to the first HttpClient
instance and call my Login
method from inside this block of code? Or can I call the Login
method later from a different block of code and then add the appropriate DefaultRequestHeader
to the other HttpClient
instances long after they have been instantiated?
public class Program
{
public static void Main()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddUserSecrets<Program>()
.AddEnvironmentVariables(); ;
IConfigurationRoot configuration = builder.Build();
var settings = new ApplicationOptions();
configuration.GetSection("AppSettings").Bind(settings);
var services = new ServiceCollection();
// This is the client I'll use to log in and get a session token
services.AddHttpClient("Authentication", c =>
{
c.BaseAddress = new Uri(settings.AuthenticationApi);
c.DefaultRequestHeaders.Accept.Clear();
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
c.DefaultRequestHeaders.Add("X-Application", settings.AppKey);
c.DefaultRequestHeaders.Add("User-Agent", "My API Client v0.0.1");
}).ConfigurePrimaryHttpMessageHandler(() =>
{
return GetMessageHandlerWithSecurityCertificate(settings);
});
// and this is the next of several clients where I'll need to send the session token with my requests
services.AddHttpClient("AnotherApi", c =>
{
c.BaseAddress = new Uri(settings.AnotherApi);
c.DefaultRequestHeaders.Accept.Clear();
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
c.DefaultRequestHeaders.Add("X-Application", settings.AppKey);
c.DefaultRequestHeaders.Add("User-Agent", "My API Client v0.0.1");
//c.DefaultRequestHeaders.Add("ssoid", sessionToken);
// What should I do here? I want to add a sessionToken string but I can only get the token's value by using the other HttpClient (above) to log in!
});
// Removed one more HttpClient for brevity
}
private static HttpMessageHandler GetMessageHandlerWithSecurityCertificate(ApplicationOptions settings)
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(GetSecurityCertificate(settings.SslCertificateFilename, settings.SslCertificatePassword));
return handler;
}
private static X509Certificate2 GetSecurityCertificate(string certFilename, string certPassword)
{
return new X509Certificate2(certFilename, certPassword);
}
}
Upvotes: 0
Views: 3468
Reputation: 1956
Can you not use the IHttpClientFactory directly and generate an HttpClient at the time you need it using your credentials? In other words, instead of trying to register all of the individual HttpClient(s), register the IHttpClientFactory as normal. Inject that into the class thats going to need the HttpClient, and just create it with your credentials there? Thats what I would do. After all, the IHttpClientFactory is simply a wrapper class which generates your HttpClients using the factory pattern.
Additionally: At a stretch you could use an extension method to configure your HttpClient with preset values to save duplicating code everywhere for consistent stuff.
Upvotes: 1