IHttpClientFactory in .NetCore _ 使用场景 & HttpRequest
Make HTTP requests using IHttpClientFactory in ASP.NET Core | Microsoft Docs
There are several ways IHttpClientFactory
can be used in an app:
The best approach depends upon the app's requirements.
Basic usage
Register IHttpClientFactory
by calling AddHttpClient
in Program.cs
:
An IHttpClientFactory
can be requested using dependency injection (DI). The following code uses IHttpClientFactory
to create an HttpClient
instance:
Using IHttpClientFactory
like in the preceding example is a good way to refactor an existing app. It has no impact on how HttpClient
is used. In places where HttpClient
instances are created in an existing app, replace those occurrences with calls to CreateClient.
Named clients
Named clients are a good choice when:
- The app requires many distinct uses of
HttpClient
. - Many
HttpClient
s have different configuration.
Specify configuration for a named HttpClient
during its registration in Program.cs
:
builder.Services.AddHttpClient("GitHub", httpClient => { httpClient.BaseAddress = new Uri("https://api.github.com/"); // using Microsoft.Net.Http.Headers; // The GitHub API requires two headers. httpClient.DefaultRequestHeaders.Add( HeaderNames.Accept, "application/vnd.github.v3+json"); httpClient.DefaultRequestHeaders.Add( HeaderNames.UserAgent, "HttpRequestsSample"); });
In the preceding code the client is configured with:
- The base address
https://api.github.com/
. - Two headers required to work with the GitHub API.
CreateClient
Each time CreateClient is called:
- A new instance of
HttpClient
is created. - The configuration action is called.
To create a named client, pass its name into CreateClient
:
In the preceding code, the request doesn't need to specify a hostname. The code can pass just the path, since the base address configured for the client is used.
Typed clients
Typed clients:
- Provide the same capabilities as named clients without the need to use strings as keys.
- Provides IntelliSense and compiler help when consuming clients.
- Provide a single location to configure and interact with a particular
HttpClient
. For example, a single typed client might be used:- For a single backend endpoint.
- To encapsulate all logic dealing with the endpoint.
- Work with DI and can be injected where required in the app.
A typed client accepts an HttpClient
parameter in its constructor:
In the preceding code:
- The configuration is moved into the typed client.
- The provided
HttpClient
instance is stored as a private field.
API-specific methods can be created that expose HttpClient
functionality. For example, the GetAspNetCoreDocsBranches
method encapsulates code to retrieve docs GitHub branches.
The following code calls AddHttpClient in Program.cs
to register the GitHubService
typed client class:
builder.Services.AddHttpClient<GitHubService>();
The typed client is registered as transient with DI. In the preceding code, AddHttpClient
registers GitHubService
as a transient service. This registration uses a factory method to:
- Create an instance of
HttpClient
. - Create an instance of
GitHubService
, passing in the instance ofHttpClient
to its constructor.
The typed client can be injected and consumed directly:
The configuration for a typed client can also be specified during its registration in Program.cs
, rather than in the typed client's constructor:
builder.Services.AddHttpClient<GitHubService>(httpClient => { httpClient.BaseAddress = new Uri("https://api.github.com/"); // ... });
Generated clients
IHttpClientFactory
can be used in combination with third-party libraries such as Refit. Refit is a REST library for .NET. It converts REST APIs into live interfaces. Call AddRefitClient
to generate a dynamic implementation of an interface, which uses HttpClient
to make the external HTTP calls.
A custom interface represents the external API:
public interface IGitHubClient { [Get("/repos/dotnet/AspNetCore.Docs/branches")] Task<IEnumerable<GitHubBranch>> GetAspNetCoreDocsBranchesAsync(); }
Call AddRefitClient
to generate the dynamic implementation and then call ConfigureHttpClient
to configure the underlying HttpClient
:
Use DI to access the dynamic implementation of IGitHubClient
:
Make POST, PUT, and DELETE requests
In the preceding examples, all HTTP requests use the GET HTTP verb. HttpClient
also supports other HTTP verbs, including:
- POST
- PUT
- DELETE
- PATCH
For a complete list of supported HTTP verbs, see HttpMethod.
The following example shows how to make an HTTP POST request:
public async Task CreateItemAsync(TodoItem todoItem) { var todoItemJson = new StringContent( JsonSerializer.Serialize(todoItem), Encoding.UTF8, Application.Json); // using static System.Net.Mime.MediaTypeNames; using var httpResponseMessage = await _httpClient.PostAsync("/api/TodoItems", todoItemJson); httpResponseMessage.EnsureSuccessStatusCode(); }
In the preceding code, the CreateItemAsync
method:
- Serializes the
TodoItem
parameter to JSON usingSystem.Text.Json
. - Creates an instance of StringContent to package the serialized JSON for sending in the HTTP request's body.
- Calls PostAsync to send the JSON content to the specified URL. This is a relative URL that gets added to the HttpClient.BaseAddress.
- Calls EnsureSuccessStatusCode to throw an exception if the response status code doesn't indicate success.
HttpClient
also supports other types of content. For example, MultipartContent and StreamContent. For a complete list of supported content, see HttpContent.
The following example shows an HTTP PUT request:
public async Task SaveItemAsync(TodoItem todoItem) { var todoItemJson = new StringContent( JsonSerializer.Serialize(todoItem), Encoding.UTF8, Application.Json); using var httpResponseMessage = await _httpClient.PutAsync($"/api/TodoItems/{todoItem.Id}", todoItemJson); httpResponseMessage.EnsureSuccessStatusCode(); }
The preceding code is similar to the POST example. The SaveItemAsync
method calls PutAsync instead of PostAsync
.
The following example shows an HTTP DELETE request:
public async Task DeleteItemAsync(long itemId) { using var httpResponseMessage = await _httpClient.DeleteAsync($"/api/TodoItems/{itemId}"); httpResponseMessage.EnsureSuccessStatusCode(); }
In the preceding code, the DeleteItemAsync
method calls DeleteAsync. Because HTTP DELETE requests typically contain no body, the DeleteAsync
method doesn't provide an overload that accepts an instance of HttpContent
.
To learn more about using different HTTP verbs with HttpClient
, see HttpClient.