0

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); } } 
0

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi, thank you for your interest and the fast response! So just thinking a bit further about your suggestion.... let's say I implement this on a Blazor app, do you imagine that the IHttpClientFactory would be passed into the constructor of every page? Would it check if each of the HttpClient instances was null and, if so, create them? Would it persist the same instance of each HttpClient across the user's session, or perhaps across the entire application lifespan?
It all depends on your architecture.. Ideally you want some sort of business layer - which is where the IHttpClientFactory could be injected.. That way it would probably just go into place.. The create method on the factory should deal with always giving you an instance, so I wouldnt worry about null checks..
Thank you Robert, I'll give the architecture some more thought and then give your idea a try.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.