HttpClientFactory - Get a named, typed client by its name
Asked Answered
D

2

19

HttpClientFactory offers the following extension method:

public static IHttpClientBuilder AddHttpClient<TClient>(this IServiceCollection services, string name)

and I've created a typed HttpClient as follows:

public class CustomClient {

    public CustomClient(HttpClient client,
        CustomAuthorizationInfoObject customAuthorizationInfoObject) {
        /// use custom authorization info to customize http client
    }

    public async Task<CustomModel> DoSomeStuffWithClient() {
        /// do the stuff
    }

}

I can register this custom client in the program's ServiceCollection as follows:

services.AddTransient<CustomAuthorizationInfoObject>();
services.AddHttpClient<CustomClient>("DefaultClient");

I can then register a second instance of this CustomClient with some slightly altered info in it:

services.AddHttpClient<CustomClient>("AlternativeAuthInfo", (client) => {
    client.DefaultRequestHeaders.Authorization = ...;
});

Elsewhere in the program I now want to get a specific named CustomClient. This is proving the obstacle.

I can get whichever CustomClient was added to services last simply by requesting CustomClient from the service provider.

Calling IHttpClientFactory.CreateClient("AlternativeAuthInfo"), for example, returns an HttpClient, so I can't access the extra method in CustomClient, and there don't appear to be any other methods there that help me.

How therefore do I go about getting a named CustomClient? Or am I misusing the opportunity to name and reference a typed client via the original extension method?

Domineering answered 6/9, 2018 at 10:23 Comment(0)
P
24

I see that there is a ITypedHttpClientFactory<> interface that can wrap a regular HttpClient in a typed one. Not used it personally, but is that the missing piece?

e.g.

/// grab the named httpclient
var altHttpClient = httpClientFactory.CreateClient("AlternativeAuthInfo");

/// get the typed client factory from the service provider
var typedClientFactory = serviceProvider.GetService<ITypedHttpClientFactory<CustomClient>>();

/// create the typed client
var altCustomClient = typedClientFactory.CreateClient(altHttpClient);
Peremptory answered 6/9, 2018 at 11:10 Comment(3)
DocsPeremptory
I had seen that but it doesn't appear to care for a name that an HttpClient has. Although I suppose I could grab the named HttpClient myself and then use that it return the typed one. I'll have a little playDomineering
Looks to be the missing piece, thanks! It feels a bit clunky - to me I wonder why IHttpClientFactory couldn't have a generic CreateClient<TypedClient>("name") method to bypass this - but nonetheless will do the jobDomineering
H
-1

I have implemented Named HttpClient Factory in .net core 3.1. Reference taken from https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1

In my startup.cs file,

services.AddHttpClient("CMAPI_Service", c =>
                {
                    c.BaseAddress = new Uri("http://192.168.0.4:44337/api/v1/");
                    //c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");// Use only for a user-agent
                    c.DefaultRequestHeaders.Accept.Clear();
                });

In my controller, call the end point using client factory as below, (here, I have made call to fetch ListItems.)

private readonly IHttpClientFactory _clientFactory;

public ControllerName(IHttpClientFactory clientFactory)
{
    _clientFactory = clientFactory;
}

For GET METHOD

HttpClient httpClient = _clientFactory.CreateClient("CMAPI_Service");
using (var response = httpClient.GetAsync("abcController/xyzAction", HttpCompletionOption.ResponseHeadersRead))
{
    response.Result.EnsureSuccessStatusCode();
    var content = response.Result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
    ViewBag.ddlEmpUIDN = JsonConvert.DeserializeObject<List<SelectListItem>>(content);
}

For POST METHOD

var content = new MultipartFormDataContent();
content.Add(new StringContent("1"), "bla bla");
content.Add(new StringContent("2"), "bla bla");

HttpClient client = _clientFactory.CreateClient("CMAPI_Service");
client.DefaultRequestHeaders.Add("Cookie", "jkl=whatever"); //Pass accordingly your requirement

var response = client.PostAsync("jklController/xyzAction", content);
response.Wait();
if (response.IsCompletedSuccessfully)
{
    //do your stuffs
}
Handrail answered 1/5 at 7:51 Comment(1)
This answer might be useful to somebody but it doesn't relate to the question. It doesn't relate to typed HttpClientsDomineering

© 2022 - 2024 — McMap. All rights reserved.