Client Configuration
See Getting started for package installation. Replace the example URLs and models with your API's values.
HttpClient Lifetime
By default, HttpRestClient acquires a shared HttpClient instance, so clients that exist at the same time use one connection pool instead of one each. The shared instance is disposed when the last client that uses it is disposed, and the next client creates a new one, so keep a client for as long as you call the API rather than creating one per call.
using Kampute.HttpClient;
using var client = new HttpRestClient();
An HttpClient resolves a host name only when it opens a connection, and it reuses open connections, so a long-lived shared instance does not follow DNS changes. On .NET Core and .NET 5 or later, set SharedHttpClient.Factory at startup, before the first client is created, to give the shared instance a SocketsHttpHandler with a PooledConnectionLifetime. Connections older than that are replaced, and the host name is resolved again. Choose the interval from how often the DNS entries of your API change.
using System;
using System.Net.Http;
using Kampute.HttpClient.Utilities;
SharedHttpClient.Factory = () => new HttpClient(new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(15)
});
If your application already manages HttpClient instances, pass one in directly. This is useful when you configure handlers, proxies, default timeouts, or dependency-injection lifetimes elsewhere.
using System;
using System.Net.Http;
using Kampute.HttpClient;
using var httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
using var client = new HttpRestClient(httpClient, disposeClient: false);
When passing an application-managed HttpClient, use disposeClient: false to keep ownership with the application. Otherwise, disposing HttpRestClient also disposes the supplied client.
Base Address
Set BaseAddress when most requests target the same API, and use relative request paths without a leading slash: a leading slash resolves the path from the host root and drops the path of the base address. The client adds a trailing slash to the base address if it has none. Register a formatter before reading typed responses.
using System;
using Kampute.HttpClient;
using Kampute.HttpClient.Json;
using var client = new HttpRestClient
{
BaseAddress = new Uri("https://api.example.com/v1/")
};
client.UseJson();
var resource = await client.GetAsync<Resource>("resources/42");
Build an API Wrapper
A typical API wrapper keeps one configured HttpRestClient and exposes domain-specific methods around it.
The Account type below is your application's response model. Both methods use relative URLs and pass cancellation to the request helper. RenameAccountAsync sends a PATCH that updates the remote account.
using System;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Kampute.HttpClient;
using Kampute.HttpClient.Json;
public sealed class AccountApiClient : IDisposable
{
private readonly HttpRestClient _client;
public AccountApiClient(Uri baseAddress, string bearerToken)
{
_client = new HttpRestClient
{
BaseAddress = baseAddress
};
_client.UseJson();
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
}
public Task<Account?> GetCurrentAccountAsync(CancellationToken cancellationToken = default)
{
return _client.GetAsync<Account>("accounts/current", cancellationToken);
}
public Task<Account?> RenameAccountAsync(string name, CancellationToken cancellationToken = default)
{
return _client.PatchAsJsonAsync<Account>("accounts/current", new { name }, cancellationToken);
}
public void Dispose()
{
_client.Dispose();
}
}
This keeps the rest of the application focused on business operations instead of repeated HTTP setup.
For temporary request settings, see Request customization.
