C
C#14mo ago
Florian Voß

✅ DI with HttpClient / HttpClientFactory

The docs show the basic usage of HttpClientFactory with DI as follows:
public class SomeService{
private IHttpClientFactory _httpFactory;
public SomeService(IHttpClientFactory httpFactory){
_httpFactory = httpFactory;
}
public void Method1(){
var client = _httpFactory.CreateClient();
//use client to do something
}
public void Method2(){
var client = _httpFactory.CreateClient();
//use client to do something
}
}
public class SomeService{
private IHttpClientFactory _httpFactory;
public SomeService(IHttpClientFactory httpFactory){
_httpFactory = httpFactory;
}
public void Method1(){
var client = _httpFactory.CreateClient();
//use client to do something
}
public void Method2(){
var client = _httpFactory.CreateClient();
//use client to do something
}
}
I wonder why not do something like this instead:
public class SomeService{
private HttpClient _client;
public SomeService(IHttpClientFactory httpFactory){
_client = httpFactory.CreateClient();
}
public void Method1(){
//use client to do something
}
public void Method1(){
//use client to do something
}
}
public class SomeService{
private HttpClient _client;
public SomeService(IHttpClientFactory httpFactory){
_client = httpFactory.CreateClient();
}
public void Method1(){
//use client to do something
}
public void Method1(){
//use client to do something
}
}
like why work with local variable and invoke CreateClient() multiple times?
72 Replies
Florian Voß
Florian Voß14mo ago
as far as I understand it won't create a new instance everytime its called but reuse an httpClient as much as possible instead which makes it even more confusing for me why we call it multiple times rather than just once
júlio
júlio14mo ago
It's a sort of Singleton from what I understand So it's the same thing It's not creating new a HttpClient, it's reusing a internal HttpClient instance for you That the Factory manages maybe it would be even better not to hold the reference and just call the .CreateClient since its a resource the Factory manages, maybe you should avoid having a reference to it with the duration of the service, but could be harmless, not sure
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
Why?
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
Isn't the HttpClientHandler deprecated?
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
I dont have any, it was just the feeling I got when trying to migrate things and reading from docs
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
Im actually having a understanding issue also regarding the IHttpClientFactory interface I made a thread for it tho, if you maybe have time https://discord.com/channels/143867839282020352/1113391788204498976
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
Im not even sure its being handled in the original code
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
I think that the things they communicate to care about cookie
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
no no i was talking about smethng else
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
not related to the OP question
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
I think that approach is nice cause you give it the host so if host changes you just go there and fix
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
I think its a issue to have so many different things that all work cause you never know which one to pick
MODiX
MODiX14mo ago
tebeco#0205
public class CorrelationIdHandler : DelegatingHandler
{
private readonly ThisHttpClientOptions _httpClientOptions;
private readonly ICorrelationIdAccessor _correlationIdAccessor;

public CorrelationIdHandler(IOption<ThisHttpClientOptions> httpClientOptions, ICorrelationIdAccessor correlationIdAccessor)
{
_httpClientOptions = httpClientOptions.Value;
_correlationIdAccessor = correlationIdAccessor;
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (!_httpClientOptions.Correlation.Enabled)
{
return await base.SendAsync(request, cancellationToken);
}

IList<string> correlationId = _correlationIdAccessor.CorrelationId;
if (correlationId.Count > 0)
{
request.Headers.Add(_configuration.Header, correlationId);
}

return await base.SendAsync(request, cancellationToken);
}
}
public class CorrelationIdHandler : DelegatingHandler
{
private readonly ThisHttpClientOptions _httpClientOptions;
private readonly ICorrelationIdAccessor _correlationIdAccessor;

public CorrelationIdHandler(IOption<ThisHttpClientOptions> httpClientOptions, ICorrelationIdAccessor correlationIdAccessor)
{
_httpClientOptions = httpClientOptions.Value;
_correlationIdAccessor = correlationIdAccessor;
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (!_httpClientOptions.Correlation.Enabled)
{
return await base.SendAsync(request, cancellationToken);
}

IList<string> correlationId = _correlationIdAccessor.CorrelationId;
if (correlationId.Count > 0)
{
request.Headers.Add(_configuration.Header, correlationId);
}

return await base.SendAsync(request, cancellationToken);
}
}
Quoted by
<@!689473681302224947> from #help-2 (click here)
React with ❌ to remove this embed.
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
translate to noob please
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
Hmm
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
So the requests client makes to my service is a incoming request, and the resquests my service makes to the outside are outcoming requests?
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
what I don't understand about TypedClient is this @TeBeClone: A Typed client is pretty much a Service that uses HttpClient right? So in your code here, FooService is a service that uses HttpClient. Now FooService is what I am writing right now and I wanna know how to inject HttpClient into FooService
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
okay but what I'm asking is not how to inject FooHttpService or FooHttpClient or whatever into services that consume it but instead I'm asking how to inject HttpClient into FooHttpService / FooHttpClient
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
so this SomeService here is the FooHttpClient that I wanna inject HttpClient into if that makes sense
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
júlio
júlio14mo ago
can you give a real world example? I thought it only needed a controller and a httpclient
Florian Voß
Florian Voß14mo ago
ok but how do you inject httpclient into the typed client
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
however you do this, I will do it like that in the Service directly and skip the Typed Client layer that was my plan
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
I know
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
you are kinda doding my question tho the question is how you inject the HttpClient into the FooHttpClient I know how to inject FooHttpClient into FooService and how to inject FooService into Controllers
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
but its not shown in here you only inject FooService and FooHttpClient. How does FooHttpClient get its HttpClient dependency?
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
ohhh that part I didn't know
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
its getting clearer and clearer for me, thx a lot
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
now in my case to get a little more concrete on the topic, I am writing WPF app and I wanna fetch Tickets from third party Api. There isn't really any business logic that needs to get applied on those tickets, I pretty much just yeet them into the UI. so the TicketService kinda is also the TicketHttpClient at the same time, is that fine? and then my MainWindow.xaml.cs consumes the TicketService / TicketHttpClient to display the tickets
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
pretty much:
public class TicketService{
private HttpClient _client;
public TicketService(HttpClient client){
_client = client;
}
public async Task<List<TicketDTO>> GetLastAcceptedAsync(){}
public async Task<List<TicketDTO>> GetMissedAsync(){}
etc.
}
public partial class MainWindow(){
private TicketService _ticketSerivce;
public MainWindow(TicketService ticketService){
_ticketService = ticketService;
}
}
public class TicketService{
private HttpClient _client;
public TicketService(HttpClient client){
_client = client;
}
public async Task<List<TicketDTO>> GetLastAcceptedAsync(){}
public async Task<List<TicketDTO>> GetMissedAsync(){}
etc.
}
public partial class MainWindow(){
private TicketService _ticketSerivce;
public MainWindow(TicketService ticketService){
_ticketService = ticketService;
}
}
builder.Services.AddHttpClient<TicketService>() That should work and is good design right? Should we name it TicketService or better TicketHttpClient or smth, its kinda all of that at same time
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
I am patient, answer me later 🙂 yep
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
that is already implemented, don't worry added all Microsfot Extensions that are needed
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
I don't really have models in that sense, I made seperation between Entities and DTOs
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
Entities for DB and DTO for any data transfer such as between different layers of my app or even beyond that
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
okay but we also suffix services with Service for the same reason and its both the TicketHttpClient and the TicketService in one type 🤷 as fetching is all I need / no business logic required
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
I just need Mainwindow => TicketService / TicketHttpClient. There is no Business logic that needs to get applied on the stuff we get from external world so I guess i just name it TicketHttpClient then and we have no Service
Unknown User
Unknown User14mo ago
Message Not Public
Sign In & Join Server To View
Florian Voß
Florian Voß14mo ago
okk
MODiX
MODiX14mo ago
tebeco#0205
and if you have ANY FORM of logic that is not linked to making request
Quoted by
React with ❌ to remove this embed.