AspNetCoreHttpKit 1.0.0
dotnet add package AspNetCoreHttpKit --version 1.0.0
NuGet\Install-Package AspNetCoreHttpKit -Version 1.0.0
<PackageReference Include="AspNetCoreHttpKit" Version="1.0.0" />
<PackageVersion Include="AspNetCoreHttpKit" Version="1.0.0" />
<PackageReference Include="AspNetCoreHttpKit" />
paket add AspNetCoreHttpKit --version 1.0.0
#r "nuget: AspNetCoreHttpKit, 1.0.0"
#:package AspNetCoreHttpKit@1.0.0
#addin nuget:?package=AspNetCoreHttpKit&version=1.0.0
#tool nuget:?package=AspNetCoreHttpKit&version=1.0.0
AspNetCoreHttpKit
A lightweight HTTP client toolkit for ASP.NET Core with typed results, structured logging (StructLog or ILogger), named clients, and configurable timeout via appsettings.json.
Why AspNetCoreHttpKit?
HttpClientin .NET is powerful but verbose. Every project ends up writing the same boilerplate: JSON serialization, error handling, logging, timeout management. AspNetCoreHttpKit wraps all of this in a clean, testable abstraction with a consistent API.
โจ Features
- ๐ GET, POST, PUT, PATCH, DELETE with automatic JSON serialization/deserialization
- ๐ฆ Result pattern โ
HttpResult<T>with fluentOnSuccess/OnError - ๐ฅ Typed exceptions โ
HttpNotFoundException,HttpUnauthorizedException, and more - โฑ๏ธ Configurable timeout โ globally and per named client
- ๐ Named clients โ one client per external service, configured in
appsettings.json - ๐ StructLog integration โ uses StructLog with typed EventCodes if registered, falls back to
ILoggerautomatically - ๐งช DI-ready โ register with one line, mock
IHttpServicein tests
๐ Requirements
| Requirement | Minimum version |
|---|---|
| .NET | 9.0+ |
| ASP.NET Core | 9.0+ |
๐ Installation
dotnet add package AspNetCoreHttpKit
๐ฏ Quick Start
1. Configure appsettings.json
{
"HttpServiceOptions": {
"BaseUrl": "https://api.myservice.com",
"TimeoutSeconds": 30,
"Clients": {
"PaymentApi": {
"BaseUrl": "https://api.payment.com",
"TimeoutSeconds": 10
},
"UserApi": {
"TimeoutSeconds": 5
}
}
}
}
UserApiinherits the globalBaseUrlbut uses its ownTimeoutSecondsof 5 seconds.PaymentApioverrides both.
2. Register services
// With StructLog (automatic detection)
builder.Services.AddStructLog(); // register StructLog first
builder.Services.AddAspNetCoreHttpKit(builder.Configuration); // HttpKit detects it automatically
// Without StructLog โ falls back to ILogger automatically
builder.Services.AddAspNetCoreHttpKit(builder.Configuration);
// Without appsettings (uses defaults)
builder.Services.AddAspNetCoreHttpKit();
3. Use the global client
[ApiController]
public class UsersController : ControllerBase
{
private readonly IHttpService _http;
public UsersController(IHttpService http)
{
_http = http;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id, CancellationToken ct)
{
var result = await _http.GetAsync<User>($"/users/{id}", ct);
return result.IsSuccess ? Ok(result.Data) : NotFound();
}
}
4. Use a named client
public class PaymentService
{
private readonly IHttpService _client;
public PaymentService(IHttpServiceFactory factory)
{
_client = factory.Create("PaymentApi");
}
public async Task<PaymentResult?> ChargeAsync(ChargeRequest request, CancellationToken ct)
{
var result = await _client.PostAsync<PaymentResult>("/charge", request, ct);
// Option A โ result pattern (fluent)
result
.OnSuccess(data => Console.WriteLine($"Charged: {data?.TransactionId}"))
.OnError((msg, code) => Console.WriteLine($"Failed: {code} โ {msg}"));
// Option B โ throw typed exception
HttpServiceHelper.ThrowIfFailed(result);
return result.Data;
}
}
๐ Logging
AspNetCoreHttpKit resolves the logger automatically at startup:
| Scenario | Logger used |
|---|---|
AddStructLog() called before AddAspNetCoreHttpKit() |
StructLog with typed EventCodes |
| StructLog not registered | Standard ILogger |
StructLog EventCodes
When StructLog is active, every HTTP operation is logged with a dedicated EventCode:
| EventCode | Description |
|---|---|
HTTP_GET_REQ / HTTP_GET_ERR |
GET request / error |
HTTP_POST_REQ / HTTP_POST_ERR |
POST request / error |
HTTP_PUT_REQ / HTTP_PUT_ERR |
PUT request / error |
HTTP_PATCH_REQ / HTTP_PATCH_ERR |
PATCH request / error |
HTTP_DELETE_REQ / HTTP_DELETE_ERR |
DELETE request / error |
HTTP_TIMEOUT |
Request timed out |
HTTP_EXCEPTION |
Unhandled exception |
๐ API Reference
IHttpService methods
| Method | Description |
|---|---|
GetAsync<T>(url, ct) |
GET request, deserializes response to T |
PostAsync<T>(url, body, ct) |
POST with JSON body, deserializes response to T |
PutAsync<T>(url, body, ct) |
PUT with JSON body, deserializes response to T |
PatchAsync<T>(url, body, ct) |
PATCH with JSON body, deserializes response to T |
DeleteAsync(url, ct) |
DELETE request, returns HttpResult |
HttpResult<T> properties
| Property | Type | Description |
|---|---|---|
IsSuccess |
bool |
true if the response was 2xx |
Data |
T? |
Deserialized response body (null on error) |
StatusCode |
HttpStatusCode |
HTTP status code |
ErrorMessage |
string? |
Error message or response body on failure |
Exception |
Exception? |
Inner exception if the request threw |
Fluent result handling
var result = await _http.GetAsync<User>("/users/1", ct);
result
.OnSuccess(user => _logger.LogInformation("Found user {Id}", user?.Id))
.OnError((msg, code) => _logger.LogWarning("Error {Code}: {Msg}", code, msg));
Typed exceptions
Use HttpService.ThrowIfFailed(result) to convert a failed result into a typed exception:
| Exception | Status code |
|---|---|
HttpBadRequestException |
400 |
HttpUnauthorizedException |
401 |
HttpForbiddenException |
403 |
HttpNotFoundException |
404 |
HttpConflictException |
409 |
HttpUnprocessableEntityException |
422 |
HttpTooManyRequestsException |
429 |
HttpServerErrorException |
500+ |
โ๏ธ Configuration options
Global options
| Option | Type | Default | Description |
|---|---|---|---|
BaseUrl |
string? |
null |
Base URL for the default client |
TimeoutSeconds |
int |
30 |
Default timeout in seconds |
Clients |
Dictionary<string, HttpClientOptions> |
{} |
Named client configurations |
Per-client options
| Option | Type | Default | Description |
|---|---|---|---|
BaseUrl |
string? |
Inherits global | Base URL override for this client |
TimeoutSeconds |
int? |
Inherits global | Timeout override for this client |
๐งช Testing
IHttpService is a plain interface โ mock it directly in unit tests:
var httpMock = new Mock<IHttpService>();
httpMock
.Setup(h => h.GetAsync<User>("/users/1", It.IsAny<CancellationToken>()))
.ReturnsAsync(HttpResult<User>.Success(new User { Id = 1, Name = "Simone" }, HttpStatusCode.OK));
โค๏ธ Support
If you find AspNetCoreHttpKit useful, consider sponsoring its development.
๐ License
MIT โ see LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Microsoft.Extensions.Configuration (>= 10.0.5)
- Microsoft.Extensions.Http (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.5)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.5)
- StructLog (>= 1.1.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on AspNetCoreHttpKit:
| Package | Downloads |
|---|---|
|
AspNetCoreResponseKit
Standardized API response envelope and global exception handling middleware for ASP.NET Core. Smart factory methods, automatic exception-to-status-code mapping, and native integration with AspNetCoreAuthKit and AspNetCoreHttpKit. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 35 | 3/25/2026 |