I am building a client of an API. My API is rather big, so I decided to split it into about 5 (private) sub-clients, each covering different part of API. 5 clients are not very comfortable to use, so I'd like to have them under 1 (public) ApiClient, which will act as a kind of facade above these 5 clients. The thing is that I probably should share one HttpClient between all these sub-clients. As far as I know, I can do something like that:
services.AddHttpClient<SubClient1>(c => c.BaseAddress = new System.Uri("https://myapi.com"));
With the above line, my SubClient1 will be injected into my public ApiClient with the proper HttpClient instance already set up with BaseAddress. Now, how do I register all 5 of my sub-clients (SubClient1, SubClient2, SubClient3, ...) so that each of them receives the same HttpClient?
I think the code below will create 5 HttpClient instances:
services.AddHttpClient<SubClient1>(c => c.BaseAddress = new System.Uri("https://myapi.com"));
services.AddHttpClient<SubClient2>(c => c.BaseAddress = new System.Uri("https://myapi.com"));
services.AddHttpClient<SubClient3>(c => c.BaseAddress = new System.Uri("https://myapi.com"));
services.AddHttpClient<SubClient4>(c => c.BaseAddress = new System.Uri("https://myapi.com"));
services.AddHttpClient<SubClient5>(c => c.BaseAddress = new System.Uri("https://myapi.com"));
How could I resolve this?
I don't disagree with @Athanasios Kataras answer. But I don't see the reason why you need to make it into a singleton.
Basically there are 3 ways to dependency inject an http client into a service; Directly, Typed, and Named. What @Athanasios did was directly. But in this scenario I believe a Named HttpClient is the way to go. But you could also just use a typed that gets injected into the subclients assuming the behavior of the client is the same across all subclients.
public class Startup
{
private IConfiguration Configuration { get; }
private IHostEnvironment HostEnvironment { get; set; }
public Startup(IConfiguration configuration, IHostEnvironment env)
{
Configuration = configuration;
HostEnvironment = env;
}
public void ConfigureServices(IServiceCollection services)
{
//Named client
services.AddHttpClient("myapi", c =>
{
c.BaseAddress = new System.Uri("https://myapi.com");
});
//Typed client
services.AddHttpClient<iMyApi, MyApi>(c =>
c.BaseAddress = new System.Uri("https://myapi.com");
});
}
}
That adds the HttpClient to the HttpClientFactory, that you can now use in whatever project.
public class SubClient
{
private readonly IHttpClientFactory httpFactory;
private readonly HttpClient namedClient;
private readonly iMyApi typedClient;
private readonly static string clientName = "myapi";
public SubClient(IHttpClientFactory httpClientFactory, iMyApi myApiClient)
{
this.namedClient = httpClientFactory.Create(clientName);
this.typedClient = myApiClient;
}
}
With the typed client it depends on you creating an implementation that implements the endpoints of your api. The advantage here is that you have a transient client that can be used in any of your services. And you free yourself from what I suspect would be a lot of duplicate code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With