Reputation: 45
I am attempting to create a singleton for an httpclientfactory in a .Net 8 console application without using the Hosting extension. I was able to get something to work, but I'm not sure that it is thread-safe as well as an actual singleton throughout the application.
One piece I am missing is how a singleton works across classes. Does DI handle that itself?
Looking at Microsoft's example at text, but was unable to apply it to my needs.
Also, note that several requests have a default request header cookie, but not all of them.
Will this work as an actual thread-safe singleton of httpclientfactory or does this create multiple instances of it?
Program.cs:
using HttpClientFactoryConsole;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
IHttpClientFactory factory = new ServiceCollection()
.AddHttpClient()
.BuildServiceProvider()
.GetRequiredService\<IHttpClientFactory\>();
HttpClient hclient = factory.CreateClient();
//use hclient to get authorization cookie
string endpoint = "https://www.microsoft.com/login";
//string response = "";
HttpResponseMessage response = new HttpResponseMessage();
string cookie;
JObject joauth = new JObject()
{
{"userName","user"},
{"password","password"}
};
HttpContent content = new StringContent(joauth.ToString());
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
try
{
//HttpClient hclient = new HttpClient();
//httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
response = await hclient.PostAsync(endpoint, content);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
cookie = response.Headers.GetValues("Set-Cookie").First();
OtherClass ot = new OtherClass(factory);
JObject setup = await ot.PermitSetupAsync(cookie);
Other class:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace HttpClientFactoryConsole
{
internal class OtherClass
{
private readonly IHttpClientFactory _httpClientFactory;
public OtherClass(IHttpClientFactory httpClientFactory) => _httpClientFactory = httpClientFactory;
public async Task<JObject> PermitSetupAsync(string authcookie)
{
HttpClient hclient = _httpClientFactory.CreateClient();
JObject jSetup = new JObject();
string setupstring = "";
Stream setupstream;
string endpoint = "http://www.microsoft.com/setup";
//string response = "";
HttpResponseMessage response = new HttpResponseMessage();
try
{
hclient.DefaultRequestHeaders.Add("Cookie", authcookie); //first add of default header?
//httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
response = await hclient.GetAsync(endpoint);
setupstream = await response.Content.ReadAsStreamAsync();
using (var streamReader = new StreamReader(setupstream))
{
setupstring = streamReader.ReadToEnd();
jSetup = (JObject)JsonConvert.DeserializeObject(setupstring);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return jSetup;
}
}
}
Upvotes: 0
Views: 320
Reputation: 1880
One piece I am missing is how a singleton works across classes. Does DI handle that itself?
Yes.
Will this work as an actual thread-safe singleton of httpclientfactory or does this create multiple instances of it?
DefaulHttpClientFactory is thread-safe and registered as singleton.
Also, note that several requests have a default request header cookie, but not all of them.
You can use named or typed clients to handle that in a clean and correct way.
Upvotes: 0