Shaunebu.Common.RESTClient 1.0.1

dotnet add package Shaunebu.Common.RESTClient --version 1.0.1
                    
NuGet\Install-Package Shaunebu.Common.RESTClient -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Shaunebu.Common.RESTClient" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Shaunebu.Common.RESTClient" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Shaunebu.Common.RESTClient" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Shaunebu.Common.RESTClient --version 1.0.1
                    
#r "nuget: Shaunebu.Common.RESTClient, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Shaunebu.Common.RESTClient@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Shaunebu.Common.RESTClient&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Shaunebu.Common.RESTClient&version=1.0.1
                    
Install as a Cake Tool

🧠 Shaunebu.RESTClient

Platform License Production Ready Performance Easy

NuGet Version

NET Support Resilience Observability Serialization CSharp Architecture

FaultTolerance Caching ThreadSafe Offline

Support

🌐 Overview

Shaunebu.RESTClient is a next-generation, attribute-driven REST client framework for .NET β€” inspired by the simplicity of Refit, but engineered from the ground up to solve the challenges of real-world enterprise environments. While Refit focuses on mapping C# interfaces to REST endpoints, RESTClient goes beyond that philosophy:

πŸ‘‰ it provides a full SDK-generation platform, ready for production, observability, resilience, and extensibility.

Modern distributed systems require more than just making HTTP calls. They demand:

  • automatic retries, timeouts, and circuit breakers

  • telemetry for tracing and performance monitoring

  • multi-format serialization (JSON, XML, MessagePack, Protobuf)

  • typed fallbacks for offline or degraded operation

  • caching, logging, and security layers

  • pluggable interceptors

  • seamless DI integration

  • progress reporting for long-running uploads/downloads

RESTClient delivers all of this out-of-the-box, with zero extra setup. It is fully declarative, fully extensible, and completely aligned with how .NET developers already work.

πŸ”§ How It Works

RESTClient dynamically generates a strongly typed REST client at runtime based on an interface decorated with attributes.
Internally, the pipeline looks like this:

Interface  
   β†’ Attribute Parser  
      β†’ Proxy Builder  
         β†’ Interceptor Pipeline  
            β†’ Serialization & Content Negotiation  
               β†’ Resilience Engine (Polly)  
                  β†’ HttpClient Transport  
                     β†’ Response Deserialization  

Each part of this pipeline is extensible, customizable, and replaceable. This architecture allows RESTClient to provide:

  • per-method resilience

  • automatic serialization based on headers

  • observability hooks

  • request/response interceptors

  • fallback logic

  • caching

  • runtime validation

  • total control over HTTP behavior

with no boilerplate.


🎯 Design Principles

RESTClient is built on a clear philosophy:

1. Declarative by Default

Developers define behavior through attributes β€” not configuration files or boilerplate.

2. Production-Ready Out-of-the-Box

Retries, timeouts, logging, diagnostics, and telemetry are enabled automatically.

3. Extensible Everywhere

Interceptors, serializers, URL formatters, fallback providers β€” all pluggable.

4. Observable by Design

Built-in OpenTelemetry tracing, metrics, and structured logging support.

5. Safe Failure Behavior

Typed fallbacks and caching allow clients to operate gracefully under failure.

6. Multi-Format Native Support

JSON, XML, MessagePack, Protobuf, FormUrlEncoded, Multipart.

7. Zero Boilerplate

A single AddRESTClient<T>() registers everything needed.

πŸš€ Why Shaunebu.RESTClient?

Refit provides a great abstraction for defining REST APIs as interfaces.
Shaunebu.RESTClient takes this philosophy and extends it into a complete, production-ready SDK framework.

  • πŸ”§ Plug-and-play registration β€” just one line of DI setup.
  • 🧱 Enterprise resilience stack β€” retries, circuit breakers, timeouts, fallback providers.
  • πŸ“¦ Multi-format serialization β€” JSON, XML, MessagePack, Protobuf, UrlEncoded.
  • 🧩 Interceptor pipeline β€” security, logging, caching, metrics, OpenTelemetry.
  • 🌐 Dynamic content negotiation based on Accept headers.
  • πŸ’₯ Fallback providers that return typed responses without throwing exceptions.
  • ⏱️ Real upload/download progress tracking.
  • βš™οΈ Extensible architecture (custom interceptors, serializers, negotiators).

πŸ“¦ Installation

dotnet add package Shaunebu.Common.RESTClient

🧭 Quick Start

public interface IPostsApi
{
    [Get("/posts")]
    Task<List<Post>> GetPostsAsync();

    [Post("/posts")]
    Task<Post> CreatePostAsync([Body] CreatePostRequest request);
}

// Dependency Injection
services.AddRESTClient<IPostsApi>("https://jsonplaceholder.typicode.com");

// Usage
var api = provider.GetRequiredService<IPostsApi>();
var result = await api.CreatePostAsync(new CreatePostRequest
{
    Title = "Hello World",
    Body = "RESTClient is amazing!"
});

βœ… No configuration needed β€” serializers, resilience policies, interceptors, and handlers are automatically registered.


βš™οΈ Centralized Configuration

All global settings are managed through RESTClientOptions:

services.AddRESTClient(options =>
{
    options.Timeout.RequestTimeoutSeconds = 30;
    options.Resilience.RetryCount = 3;
    options.Resilience.CircuitBreakerThreshold = 5;
    options.DefaultCollectionFormat = CollectionFormat.Csv;
    options.BufferResponse = true;
});

Example of appsettings.json registration

{
  "RestClients": [
    {
      "Interface": "MyApp.Api.IPostsApi, MyApp",
      "BaseUrl": "https://jsonplaceholder.typicode.com"
    }
  ]
}

Then:

services.AddRESTClientsFromConfig(Configuration);

🧩 Attribute Reference

Attribute Purpose
[Get], [Post], [Put], [Delete], [Patch], [Head] Declares HTTP methods
[Body(Method = ...)] Selects serialization format (JSON, XML, MsgPack, etc.)
[Query(Format=..., CollectionFormat=...)] Controls query parameter encoding
[Host("https://...")] Overrides the default host per method
[Fallback(typeof(MyFallback))] Defines a typed fallback provider
[Retry], [Timeout], [CircuitBreaker], [Bulkhead] Method-level resilience controls
[Headers], [Header], [AliasAs] Header customization
[Multipart(Boundary="...")] Full multipart upload control
[RateLimit], [HealthCheck] Advanced traffic and availability controls

πŸ“œ Multi-Serialization and Content Negotiation

Shaunebu.RESTClient can serialize and deserialize payloads dynamically based on the Accept or Content-Type headers.

[Post("/users")]
Task<User> AddUser([Body(Method = BodySerializationMethod.Json)] User user);

[Post("/files/upload")]
[Multipart(Boundary = "----CustomBoundary")]
Task<ApiResponse<string>> UploadFile([AliasAs("file")] StreamPart file);

Supported Serializers

Format MIME Type Implementation
JSON application/json SystemTextJsonSerializer / NewtonsoftJsonSerializer
XML application/xml XmlContentSerializer
MessagePack application/x-msgpack MessagePackSerializer
Protobuf application/x-protobuf ProtobufSerializer
FormUrlEncoded application/x-www-form-urlencoded UrlEncodedContentSerializer

You can register your own serializers:

services.TryAddSingleton<IContentSerializer, MyCustomSerializer>();

🧠 Dynamic Content Negotiation

The ContentNegotiator automatically chooses the correct serializer based on the request’s Accept header. Example:

[Get("/data")]
[Headers("Accept: application/x-protobuf")]
Task<MyResponse> GetDataInProtobuf();

The library will automatically:

  • use ProtobufSerializer to serialize/deserialize the body,

  • and send the correct Content-Type.


πŸ’ͺ Declarative Resilience (Polly Built-In)

Built-in attribute-level resilience, powered by Polly:

[Get("/data")]
[Retry(3, 2)] // Retries with exponential backoff
[Timeout(5)] // Timeout after 5 seconds
[CircuitBreaker(3, 10)] // Breaks circuit after 3 errors for 10s
Task<DataResponse> GetDataAsync();

No need to register Polly handlers manually β€” everything is wired automatically through DI.


πŸ’₯ Typed Fallback Providers

If a request fails, the fallback provider can return a typed result instead of throwing an exception.

[Get("/users/{id}")]
[Fallback(typeof(UserFallbackProvider))]
Task<User> GetUserAsync(int id);

public class UserFallbackProvider
{
    public Task<User> GetFallbackAsync(Exception ex) =>
        Task.FromResult(new User { Id = -1, Name = "Offline User" });
}

When triggered, the response includes a header:

X-Fallback-Executed: true

⏱️ Progress Tracking

Real-time upload and download progress tracking using IProgress<double>:

[Post("/upload")]
Task<ApiResponse> UploadLargeFileAsync([Body] StreamPart file, IProgress<double> progress);

The progress value reports 0.0 β†’ 1.0 (0% β†’ 100%).


πŸ”„ Interceptors and Middleware

Interceptors allow you to hook into the entire request/response lifecycle.

public class MyLoggingInterceptor : IRESTInterceptor
{
    public Task OnRequestAsync(RequestContext ctx)
    {
        Console.WriteLine($"➑️ {ctx.Request.Method} {ctx.Request.RequestUri}");
        return Task.CompletedTask;
    }

    public Task OnResponseAsync(ResponseContext ctx)
    {
        Console.WriteLine($"⬅️ {ctx.Response.StatusCode}");
        return Task.CompletedTask;
    }
}

Add via DI:

services.TryAddSingleton<IRESTInterceptor, MyLoggingInterceptor>();

Built-in Interceptors

  • πŸ” SecurityInterceptor

  • 🧱 ResilienceInterceptor

  • πŸͺ£ CachingInterceptor

  • 🧭 OpenTelemetryInterceptor

  • πŸͺ΅ LoggingInterceptor

  • πŸ§ͺ DebugInterceptor

  • πŸ’₯ FallbackInterceptor

  • βš™οΈ PollyDebugInterceptor

  • πŸ“Š MetricsInterceptor


🧱 Caching and Metrics

Out of the box support for:

  • ICacheStore (default: MemoryCacheStore)

  • CachingInterceptor (automatic response caching)

  • OpenTelemetry tracing (OpenTelemetryInterceptor)

  • Metrics gathering (MetricsInterceptor)


πŸ“Š Full Feature Comparison

Feature Shaunebu RESTClient Refit
Unified DI Registration (AddRESTClient) βœ… ❌
Centralized Config (RESTClientOptions) βœ… ⚠️
Content Negotiation βœ… ❌
Multiple Serializers βœ… ⚠️
Newtonsoft + System.Text.Json βœ… βœ…
Per-method Serializer βœ… ❌
Accept Header Auto-Detection βœ… ❌
Multipart Boundary Control βœ… ⚠️
Upload/Download Progress βœ… ❌
[Retry], [Timeout], [CircuitBreaker] βœ… ❌
Typed Fallbacks βœ… ❌
Polly Integration (Automatic) βœ… ⚠️
RateLimit / Bulkhead / HealthCheck βœ… ❌
Interceptors (Pipeline) βœ… ❌
Built-in Logging & Telemetry βœ… ⚠️
Response Caching βœ… ❌
AppSettings Config Integration βœ… ❌
Query Formatting (CollectionFormat) βœ… ⚠️
[Host] Attribute βœ… ❌
IApiResponse<T> Support βœ… βœ…
Content-Type Aware Deserialization βœ… ❌
NoThrowPolicy for graceful error handling βœ… ❌
Source Generator & Proxy Fallback βœ… βœ…
Production-Ready Stack βœ… ❌

🧠 Deep Comparison with Refit

While Refit is excellent for lightweight API calls, it has limitations in enterprise scenarios:

Refit is ideal for:

  • Simple REST wrappers

  • Mobile apps

  • Low-infrastructure projects

  • Rapid prototypes

RESTClient is designed for:

  • Microservices

  • Enterprise APIs

  • SDK development

  • Mission-critical integrations

  • Highly observable systems

  • Environments where resiliency is mandatory

In short:
Refit helps you call APIs β€” RESTClient helps you build SDKs for APIs.


🧩 Extending Shaunebu.RESTClient

Custom Serializer

Implement IContentSerializer to plug in any serialization logic.

Custom Interceptor

Add your own interceptor for metrics, logging, or security checks.

Custom Fallback Provider

Attach to [Fallback(typeof(...))] for custom recovery logic.

Custom Url Parameter Formatter

Implement IUrlParameterFormatter to change query escaping globally.


🧩 Example: Complex Client Definition

[Headers("Authorization: Bearer")]
[Host("https://api.override.com")]
public interface IComplexApi
{
    [Get("/users/{id}")]
    [Fallback(typeof(UserFallback))]
    [Retry(3, 1)]
    [Timeout(10)]
    Task<User> GetUserAsync(int id);

    [Post("/upload")]
    [Multipart(Boundary = "----ShaunebuBoundary")]
    Task<ApiResponse> UploadFileAsync([AliasAs("file")] StreamPart file, IProgress<double> progress);
}

  • 🧱 SDK Generation for enterprise APIs

  • ☁️ Microservice Clients with per-method resiliency

  • 🧩 Highly observable integrations (with OpenTelemetry)

  • πŸ“Š Data ingestion services requiring metrics and caching

  • πŸ’Ύ Offline-capable APIs using fallbacks and memory cache


🧩 Credits

Originally inspired by Refit, but re-engineered by Jorge Perales DΓ­az
for real-world, large-scale systems that need reliability, observability, and full-stack resilience.


πŸ—ΊοΈ ** Roadmap **

πŸš€ Feature 🧩 Status 🎯 Target Version πŸ“… ETA πŸ“˜ Notes
βœ… Core Framework Stabilization 🟒 Completed v1.0.0 Q4 2024 Core system finalized β€” DI registration, interceptors, serializers, Polly, caching & fallbacks.
βœ… Multi-Serialization Stack (JSON / XML / MessagePack / Protobuf) 🟒 Completed v1.0.0 Q4 2024 Content negotiation via headers, per-method [Body] serializer selection.
βš™οΈ Resilience Engine v2 🟑 In Progress v1.1.0 Feb 2025 Policy registry, adaptive retry & dynamic backoff support.
πŸ” Token Provider & Auth Interceptor 🟑 In Progress v1.1.0 Apr 2025 OAuth / JWT auto-refresh through ITokenProvider.
πŸ’Ύ Caching Enhancements v2 🟑 In Progress v1.1.0 May 2025 Redis / SQLite cache providers and configurable policies.
🧠 RestClientMonitor (Dashboard & Telemetry) πŸ”΅ Planned v1.2.0 Dec 2025 🧩 Embedded monitor endpoint (/_restclient/monitor) showing latency, retries, cache hits & failures.
πŸͺ΅ Structured Logging & Audit Trail πŸ”΅ Planned v1.2.0 Dec 2025 JSON log formatter + PII masking for GDPR compliance.
🧭 OpenTelemetry Enricher Hooks πŸ”΅ Planned v1.2.0 Jun 2025 Custom span tags & metrics from RESTClient context.
βš™οΈ Dynamic Interceptor Pipeline πŸ”΅ Planned v1.3.0 Aug 2025 Add / remove interceptors dynamically at runtime.
πŸ§ͺ In-Memory Mock Transport πŸ”΅ Planned v1.3.0 Sep 2025 Offline transport for testing (FakeHttpHandler).
πŸͺΆ Source Generator Integration πŸ”΅ Planned v1.4.0 Nov 2025 Build-time proxy generator via incremental Roslyn.
πŸ“Š CLI Tool for OpenAPI Import πŸ”΅ Planned v1.4.0 Dec 2025 dotnet restclient import openapi.json β€” automatic interface generation.
🧾 RESTClient Analyzer Package πŸ”΅ Planned v1.4.0 Dec 2025 Roslyn analyzers warning about missing attributes / timeouts.
🧱 SignalR Integration πŸ”΅ Planned v1.5.0 Q1 2026 Bridge REST ↔ SignalR with automatic message routing.

πŸ“„ License

MIT Β© Shaunebu 2025

Product 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 661 12/1/2025
1.0.0 652 12/1/2025