RESTCLIENT.NET / DOCUMENTATION
IHttpClientFactory Extensions
Extension methods for System.Net.Http.IHttpClientFactory that provide the same type-safe HTTP operations as the HttpClient extensions, with built-in client creation and connection pooling.
Namespace: RestClient.Net
Overview
These extension methods work with IHttpClientFactory from Microsoft.Extensions.Http, enabling proper HTTP connection management in ASP.NET Core applications.
SendAsync
The core method for sending HTTP requests with full control over all parameters.
public static async Task<Result<TSuccess, HttpError<TError>>> SendAsync<TSuccess, TError>(
this IHttpClientFactory httpClientFactory,
string clientName,
AbsoluteUrl url,
HttpMethod httpMethod,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError,
HttpContent? requestBody = null,
IReadOnlyDictionary<string, string>? headers = null,
HttpAction? httpOperation = null,
CancellationToken cancellationToken = default
)
Parameters
| Parameter | Type | Description |
|---|---|---|
httpClientFactory |
IHttpClientFactory |
The HTTP client factory instance |
clientName |
string |
The name of the configured HTTP client |
url |
AbsoluteUrl |
The absolute URL for the request |
httpMethod |
HttpMethod |
The HTTP method (GET, POST, PUT, etc.) |
deserializeSuccess |
Deserialize<TSuccess> |
Async function to deserialize successful responses |
deserializeError |
Deserialize<TError> |
Async function to deserialize error responses |
requestBody |
HttpContent? |
Optional request body content |
headers |
IReadOnlyDictionary<string, string>? |
Optional request headers |
httpOperation |
HttpAction? |
Optional custom HTTP operation handler |
cancellationToken |
CancellationToken |
Cancellation token |
GetAsync
Performs a GET request using a named HTTP client.
public static Task<Result<TSuccess, HttpError<TError>>> GetAsync<TSuccess, TError>(
this IHttpClientFactory httpClientFactory,
string clientName,
AbsoluteUrl url,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError,
IReadOnlyDictionary<string, string>? headers = null,
CancellationToken cancellationToken = default
)
Example
// In Program.cs - configure the named client
builder.Services.AddHttpClient("api", client =>
{
client.BaseAddress = new Uri("https://api.example.com");
client.DefaultRequestHeaders.Add("Accept", "application/json");
});
// In your service - use the factory
public class UserService(IHttpClientFactory factory)
{
public async Task<Result<User, HttpError<ApiError>>> GetUserAsync(int id)
{
return await factory.GetAsync(
clientName: "api",
url: $"https://api.example.com/users/{id}".ToAbsoluteUrl(),
deserializeSuccess: DeserializeJson<User>,
deserializeError: DeserializeJson<ApiError>
);
}
}
PostAsync
Performs a POST request with a request body.
public static Task<Result<TSuccess, HttpError<TError>>> PostAsync<TSuccess, TError>(
this IHttpClientFactory httpClientFactory,
string clientName,
AbsoluteUrl url,
HttpContent? requestBody,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError,
IReadOnlyDictionary<string, string>? headers = null,
CancellationToken cancellationToken = default
)
PutAsync
Performs a PUT request with a request body.
public static Task<Result<TSuccess, HttpError<TError>>> PutAsync<TSuccess, TError>(
this IHttpClientFactory httpClientFactory,
string clientName,
AbsoluteUrl url,
HttpContent? requestBody,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError,
IReadOnlyDictionary<string, string>? headers = null,
CancellationToken cancellationToken = default
)
DeleteAsync
Performs a DELETE request.
public static Task<Result<TSuccess, HttpError<TError>>> DeleteAsync<TSuccess, TError>(
this IHttpClientFactory httpClientFactory,
string clientName,
AbsoluteUrl url,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError,
IReadOnlyDictionary<string, string>? headers = null,
CancellationToken cancellationToken = default
)
PatchAsync
Performs a PATCH request with a request body.
public static Task<Result<TSuccess, HttpError<TError>>> PatchAsync<TSuccess, TError>(
this IHttpClientFactory httpClientFactory,
string clientName,
AbsoluteUrl url,
HttpContent requestBody,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError,
IReadOnlyDictionary<string, string>? headers = null,
CancellationToken cancellationToken = default
)
DownloadFileAsync
Downloads a file from the specified URL to a stream.
public static Task<Result<Unit, HttpError<TError>>> DownloadFileAsync<TError>(
this IHttpClientFactory httpClientFactory,
string clientName,
AbsoluteUrl url,
Stream destinationStream,
Deserialize<TError> deserializeError,
IReadOnlyDictionary<string, string>? headers = null,
CancellationToken cancellationToken = default
)
UploadFileAsync
Uploads a file with progress reporting.
public static Task<Result<TSuccess, HttpError<TError>>> UploadFileAsync<TSuccess, TError>(
this IHttpClientFactory httpClientFactory,
string clientName,
AbsoluteUrl url,
ProgressReportingHttpContent fileStream,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError,
IReadOnlyDictionary<string, string>? headers = null,
CancellationToken cancellationToken = default
)
Request Factory Methods
These static methods create reusable request delegates.
CreateGet
public static GetAsync<TSuccess, TError, TParam> CreateGet<TSuccess, TError, TParam>(
AbsoluteUrl url,
BuildRequest<TParam> buildRequest,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError
)
CreatePost
public static PostAsync<TSuccess, TError, TParam> CreatePost<TSuccess, TError, TParam>(
AbsoluteUrl url,
BuildRequest<TParam> buildRequest,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError
)
CreatePut
public static PutAsync<TSuccess, TError, TParam> CreatePut<TSuccess, TError, TParam>(
AbsoluteUrl url,
BuildRequest<TParam> buildRequest,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError
)
CreateDelete
public static DeleteAsync<TSuccess, TError, TParam> CreateDelete<TSuccess, TError, TParam>(
AbsoluteUrl url,
BuildRequest<TParam> buildRequest,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError
)
CreatePatch
public static PatchAsync<TSuccess, TError, TParam> CreatePatch<TSuccess, TError, TParam>(
AbsoluteUrl url,
BuildRequest<TParam> buildRequest,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError
)
CreateHead
public static HeadAsync<TSuccess, TError, TParam> CreateHead<TSuccess, TError, TParam>(
AbsoluteUrl url,
BuildRequest<TParam> buildRequest,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError
)
CreateOptions
public static OptionsAsync<TSuccess, TError, TParam> CreateOptions<TSuccess, TError, TParam>(
AbsoluteUrl url,
BuildRequest<TParam> buildRequest,
Deserialize<TSuccess> deserializeSuccess,
Deserialize<TError> deserializeError
)
Configuration Example
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// Configure named HTTP clients
builder.Services.AddHttpClient("github", client =>
{
client.BaseAddress = new Uri("https://api.github.com");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
});
builder.Services.AddHttpClient("internal-api", client =>
{
client.BaseAddress = new Uri("https://internal.example.com");
})
.AddPolicyHandler(GetRetryPolicy()); // Add Polly policies
// Register services that use the factory
builder.Services.AddScoped<IGitHubService, GitHubService>();
Best Practices
- Use named clients - Configure different clients for different APIs
- Configure base addresses - Set
BaseAddressin the client configuration - Add default headers - Configure common headers like Accept, Authorization
- Use Polly - Add retry and circuit breaker policies for resilience
- Avoid capturing HttpClient - Let the factory create new clients as needed