Detailed explanation of HTTP request IHttpClientFactory example under Net Core

  • 2021-11-10 09:24:42
  • OfStack

Directory usage
Basic usage
Named client
Typed client
Generated client
Outbound request middleware
HttpClient and Life Cycle

Usage

IHttpClientFactory has four modes:

Basic usage Named client Typed client Generated client

Basic usage

In the Startup. ConfigureServices method, IHttpClientFactory can be registered by calling the AddHttpClient extension method on IServiceCollection


services.AddHttpClient();

After registration, it can be used in the class through constructor injection like dependency injection DI. Pseudocode:


class A
{
 private readonly IHttpClientFactory _clientFactory;
 public A(IHttpClientFactory clientFactory)
 {
  _clientFactory = clientFactory;
 }
 
 Public void Use()
 {
   var request=new HttpRequestMessage(HttpMethod.Get,"www.baidu.com") ;
   var client = _clientFactory.CreateClient();
   var response = await client.SendAsync(request); 
   if (response.IsSuccessStatusCode)
   {
   Branches = await response.Content.ReadAsAsync<IEnumerable<GitHubBranch>>();
   }
  else
  {
   GetBranchesError = true;
   Branches = Array.Empty<GitHubBranch>();
  }  
 }
}

Named client

It also adds configuration parameters on the basis of basic usage: for example, add 1 client under baidu:


services.AddHttpClient("baidu",c=>
{
 c.BaseAddress = new Uri("https://api.baidu.com/");
 // Others 1 Some parameters 
});

Then, when using it, you only need to pass the client name to automatically use the basic address configuration of baidu address:


 var client = _clientFactory.CreateClient("baidu");

Typed client

The clear point is that you can directly accept the HttpClient type in the constructor using the class, instead of creating it in the CreateClient method using the IHttpClientFactory interface, but the first condition is to create the injection type first, and then inject it in the ConfigureServices method at the same time:


services.AddHttpClient<classHttp>();

Injection type:


public class classHttp
{
   public HttpClient Client { get; }
   public GitHubService(HttpClient client)
   {
      client.BaseAddress = new Uri("https://api.baidu.com/");
      // Same as ConfigureServices  Medium 1 Sample setting 1 Some other parameters 
      Client = client;
   }
}

Generated client

I personally understand this is to configure the use of the third-party library, and then can inject interface types, interfaces can write some method interfaces. Then call the interface directly through the interface class.

Personal understanding: It is similar to an interface mapping and an address mapping. By combining with the third-party library (officially recommended Refit), we can request an address alias, which refers to the defined interface. The alias is then redirected to the real request interface address by adding the attributes Get ("Path") or post ("Path"). Translate the real address of the request by requesting this local interface method.

Examples define interfaces:


public interface IHelloClient
{
  [Get("/MyInterFace")]
  Task<Reply> GetMessageAsync();
}

Configure the Refit plug-in:

Similar to the normal configuration, the service injection of interface is added at the back.


public void ConfigureServices(IServiceCollection services)
{
  services.AddHttpClient("hello", c =>
  {
    c.BaseAddress = new Uri("http://localhost:5000");
  })
  .AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));

  services.AddMvc();
}

Then talk about the Get ("/MyInterFace") method on the interface; We won't do this. Another project is under the current project, so we can create a method called MyInterFace directly under the api project.


[ApiController]
public class TestController : ControllerBase
{
   [HttpGet("/")]
  public async Task<sting> MyInterFace()
  {
    return "ceshi";
  }
}

Then you can use the interface:


[ApiController]
public class ValuesController : ControllerBase
{
  private readonly IHelloClient _client;

  public ValuesController(IHelloClient client)
  {
    _client = client;
  }

  [HttpGet("/")]
  public async Task<ActionResult<Reply>> Index()
  {
    return await _client.GetMessageAsync();
  }
}

The _ client. GetMessageAsync () method here is to call the interface method. It seems that the GetMessageAsync method is actually mapped, and the mapping address is the MyInterFace method written by the above feature. This conclusion can also be verified by breakpoints. Then different items are also the same meaning, if we request Baidu's address: www.baidu.com/api/b this interface

In the configuration, we change the request address http://localhost: 5000 to www. baidu. com/api, and then change MyInterFace above GetMessageAsync method to b.

Outbound request middleware

Personal understanding of the request to return to the pre-handler, is to inherit the DelegatingHandler derived class override SendAsync method. Execute the code before passing the request to the next 1 handler in the pipeline:


class A
{
 private readonly IHttpClientFactory _clientFactory;
 public A(IHttpClientFactory clientFactory)
 {
  _clientFactory = clientFactory;
 }
 
 Public void Use()
 {
   var request=new HttpRequestMessage(HttpMethod.Get,"www.baidu.com") ;
   var client = _clientFactory.CreateClient();
   var response = await client.SendAsync(request); 
   if (response.IsSuccessStatusCode)
   {
   Branches = await response.Content.ReadAsAsync<IEnumerable<GitHubBranch>>();
   }
  else
  {
   GetBranchesError = true;
   Branches = Array.Empty<GitHubBranch>();
  }  
 }
}
0

Then in ConfigureServices:


class A
{
 private readonly IHttpClientFactory _clientFactory;
 public A(IHttpClientFactory clientFactory)
 {
  _clientFactory = clientFactory;
 }
 
 Public void Use()
 {
   var request=new HttpRequestMessage(HttpMethod.Get,"www.baidu.com") ;
   var client = _clientFactory.CreateClient();
   var response = await client.SendAsync(request); 
   if (response.IsSuccessStatusCode)
   {
   Branches = await response.Content.ReadAsAsync<IEnumerable<GitHubBranch>>();
   }
  else
  {
   GetBranchesError = true;
   Branches = Array.Empty<GitHubBranch>();
  }  
 }
}
1

You can register multiple handlers at the same time.

HttpClient and Life Cycle

Each call to CreateClient on IHttpClientFactory returns a new HttpClient instance. Each named client has one HttpMessageHandler. The factory manages the lifetime of HttpMessageHandler instances.

HttpClient instances are not destroyed with HttpMessageHandler1. HttpMessageHandler lives in the pool and will be used by new HttpClient instances if their life cycle is not destroyed.

The default life cycle of the handler is 2 minutes, which can be modified by configuration:


class A
{
 private readonly IHttpClientFactory _clientFactory;
 public A(IHttpClientFactory clientFactory)
 {
  _clientFactory = clientFactory;
 }
 
 Public void Use()
 {
   var request=new HttpRequestMessage(HttpMethod.Get,"www.baidu.com") ;
   var client = _clientFactory.CreateClient();
   var response = await client.SendAsync(request); 
   if (response.IsSuccessStatusCode)
   {
   Branches = await response.Content.ReadAsAsync<IEnumerable<GitHubBranch>>();
   }
  else
  {
   GetBranchesError = true;
   Branches = Array.Empty<GitHubBranch>();
  }  
 }
}
2

Summarize


Related articles: