ZeroAlloc.Rest.Tools
1.1.0
See the version list below for details.
dotnet tool install --global ZeroAlloc.Rest.Tools --version 1.1.0
dotnet new tool-manifest
dotnet tool install --local ZeroAlloc.Rest.Tools --version 1.1.0
#tool dotnet:?package=ZeroAlloc.Rest.Tools&version=1.1.0
nuke :add-package ZeroAlloc.Rest.Tools --version 1.1.0
ZeroAlloc.Rest
ZeroAlloc.Rest is a source-generated, Native AOT-compatible REST client for .NET 10+. Define your HTTP API as a C# interface — the Roslyn generator emits a fully type-safe, zero-reflection implementation at compile time. No runtime code generation, no IL emit, no allocations beyond the HTTP layer itself.
Install
The source generator is bundled into the main package — a single PackageReference is all you need:
dotnet add package ZeroAlloc.Rest
dotnet add package ZeroAlloc.Rest.SystemTextJson
Or via <PackageReference>:
<PackageReference Include="ZeroAlloc.Rest" Version="x.y.z" />
<PackageReference Include="ZeroAlloc.Rest.SystemTextJson" Version="x.y.z" />
The standalone
ZeroAlloc.Rest.Generatorpackage is still published for backwards compatibility with existing direct PackageReferences, but new consumers should reference onlyZeroAlloc.Rest.
Optional: resilience policies
To add retry, timeout, and circuit-breaker behaviour to a client, install the bridge package alongside ZeroAlloc.Resilience:
dotnet add package ZeroAlloc.Rest.Resilience
dotnet add package ZeroAlloc.Resilience
Quick Start
1. Define your API interface:
using ZeroAlloc.Rest.Attributes;
[ZeroAllocRestClient]
public interface IUserApi
{
[Get("/users/{id}")]
Task<UserDto> GetUserAsync(int id, CancellationToken ct = default);
[Get("/users")]
Task<List<UserDto>> ListUsersAsync([Query] string? name = null, CancellationToken ct = default);
[Post("/users")]
Task<UserDto> CreateUserAsync([Body] CreateUserRequest request, CancellationToken ct = default);
[Delete("/users/{id}")]
Task DeleteUserAsync(int id, CancellationToken ct = default);
}
2. Register in DI:
builder.Services.AddIUserApi(options =>
{
options.BaseAddress = new Uri("https://api.example.com");
options.UseSerializer<SystemTextJsonSerializer>();
});
3. Inject and use:
public class UserService(IUserApi api)
{
public Task<UserDto> GetAsync(int id) => api.GetUserAsync(id);
}
The generator produces UserApiClient — a sealed class implementing IUserApi — at compile time. No reflection, no proxies, no DynamicMethod.
Performance
Measured on .NET 10.0.4, Windows 11, X64. In-memory handler; no real network I/O. See docs/benchmarks.md for methodology and full results.
| Method | Mean | vs Refit | Allocated |
|---|---|---|---|
| Raw HttpClient (GET baseline) | 1,648 ns | — | 1.38 KB |
| ZeroAlloc.Rest GET | 1,933 ns | 3.2× faster | 1.74 KB |
| Refit GET | 6,123 ns | 1× | 3.03 KB |
| ZeroAlloc.Rest QueryParam | 2,474 ns | 5.5× faster | 1.85 KB |
| Refit QueryParam | 13,509 ns | 1× | 3.67 KB |
Features
- Source-generated — zero runtime reflection; compile-time type safety
- Native AOT compatible — no
DynamicMethod, no IL emit, noType.GetType - Per-method serializer override —
[Serializer(typeof(MySerializer))]for mixed protocols - Path, query, body, and header parameters —
{id},[Query],[Body],[Header("X-Api-Key")] Result<T, HttpError>— typed success/error returns viaZeroAlloc.Results; no exception-throwing on 4xx/5xx- OpenAPI code generation —
OpenApiInterfaceGeneratorAPI + MSBuild<ZeroAllocApiSpec>task - Pluggable serializers — System.Text.Json, MemoryPack, MessagePack, or bring your own
- IHttpClientFactory integration —
AddI{Interface}generated extension method - Resilience bridge —
ZeroAlloc.Rest.Resiliencewraps any client with[Retry],[Timeout],[CircuitBreaker], and[RateLimit]viaAddRestResilience<,,>()
Telemetry
Every generated client emits OpenTelemetry-compatible signals out of the box, with no extra dependency beyond the BCL System.Diagnostics primitives.
Tracing. An ActivitySource("ZeroAlloc.Rest") produces one span per call, named Interface.Method. Tags: http.method, http.status_code, server.address, rest.method. Exceptions set ActivityStatusCode.Error with the message.
Metrics. The generator emits rest.requests_total (counter) and rest.request_duration_ms (histogram) under the ZeroAlloc.Rest Meter. Tags: http.method, http.status_code, server.address, rest.method (the generated Interface.Method identifier).
The counter is incremented only on the success path. On exception, the histogram records the elapsed duration but the counter is left untouched — this lets operators distinguish failed attempts via histogram count vs. counter delta. The exception-path histogram carries only http.method and rest.method, since http.status_code and server.address may not be known.
Subscription:
services.AddOpenTelemetry()
.WithTracing(t => t.AddSource("ZeroAlloc.Rest"))
.WithMetrics(m => m.AddMeter("ZeroAlloc.Rest"));
Documentation
| Page | Description |
|---|---|
| Getting Started | Install, register, and make your first call |
| Routing | Route templates and path parameters |
| Parameters | Query, body, header, and path parameters |
| Serialization | Built-in serializers and custom IRestSerializer |
| Dependency Injection | Generated DI extension and IHttpClientFactory |
| Native AOT | AOT safety guarantees and publish configuration |
| OpenAPI Code Generation | Generate interfaces from OpenAPI specs |
| Benchmarks | Performance comparison vs Refit and raw HttpClient |
| Testing | Testing patterns with WireMock.Net |
| Advanced | Result<T, HttpError>, multiple serializers, edge cases |
| Resilience | Retry, timeout, circuit-breaker, and rate-limit via ZeroAlloc.Rest.Resilience |
| Cookbook | End-to-end recipes |
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.3 | 88 | 5/13/2026 |
| 1.1.2 | 89 | 5/12/2026 |
| 1.1.1 | 91 | 5/2/2026 |
| 1.1.0 | 89 | 5/1/2026 |
| 1.0.2 | 107 | 4/29/2026 |
| 1.0.1 | 103 | 4/29/2026 |
| 1.0.0 | 105 | 4/28/2026 |
| 0.2.0 | 101 | 4/14/2026 |
| 0.1.5 | 99 | 4/25/2026 |
| 0.1.4 | 102 | 4/25/2026 |
| 0.1.3 | 96 | 4/14/2026 |
| 0.1.2 | 120 | 4/2/2026 |
| 0.1.1 | 112 | 4/1/2026 |
| 0.1.0 | 105 | 3/31/2026 |