Atc.Rest.Client
2.0.1
See the version list below for details.
dotnet add package Atc.Rest.Client --version 2.0.1
NuGet\Install-Package Atc.Rest.Client -Version 2.0.1
<PackageReference Include="Atc.Rest.Client" Version="2.0.1" />
<PackageVersion Include="Atc.Rest.Client" Version="2.0.1" />
<PackageReference Include="Atc.Rest.Client" />
paket add Atc.Rest.Client --version 2.0.1
#r "nuget: Atc.Rest.Client, 2.0.1"
#:package Atc.Rest.Client@2.0.1
#addin nuget:?package=Atc.Rest.Client&version=2.0.1
#tool nuget:?package=Atc.Rest.Client&version=2.0.1
ATC.Net REST Client
A lightweight and flexible REST client library for .NET, providing a clean abstraction over HttpClient with built-in support for request building, response handling, and dependency injection.
Table of Contents
- ATC.Net REST Client
Features
- Fluent HTTP Request Building: Build complex HTTP requests with a clean, chainable API
- Typed Response Handling: Strongly-typed success and error responses
- Flexible Configuration: Multiple ways to configure HTTP clients
- Dependency Injection Ready: Seamless integration with Microsoft.Extensions.DependencyInjection
- Path Templates: Support for URI templates with parameter replacement
- Query & Header Parameters: Easy addition of query strings and headers
- Custom Serialization: Pluggable contract serialization (defaults to JSON)
- Response Processing: Built-in support for success/error response handling
Getting Started
Installation
Install the package via NuGet:
dotnet add package Atc.Rest.Client
Service Registration
There are two ways to register an HTTP client with dependency injection:
Approach 1: Direct Configuration (Recommended for Simple Cases)
Use this approach when you have straightforward configuration needs:
using Atc.Rest.Client.Options;
services.AddAtcRestClient(
clientName: "MyApiClient",
baseAddress: new Uri("https://api.example.com"),
timeout: TimeSpan.FromSeconds(30));
Approach 2: Custom Options Type
Use this approach when you need to register the options as a singleton for later retrieval:
// Define a custom options class
public sealed class MyApiClientOptions : AtcRestClientOptions
{
public string ApiKey { get; set; } = string.Empty;
}
// Register with custom options
var options = new MyApiClientOptions
{
BaseAddress = new Uri("https://api.example.com"),
Timeout = TimeSpan.FromSeconds(30),
ApiKey = "your-api-key"
};
services.AddAtcRestClient(
clientName: "MyApiClient",
options: options);
Creating an Endpoint
Create an endpoint class that uses IHttpMessageFactory to build and send requests:
public interface IUsersEndpoint
{
Task<EndpointResponse<User>> GetUserAsync(int userId, CancellationToken cancellationToken = default);
}
public class UsersEndpoint : IUsersEndpoint
{
private readonly IHttpClientFactory clientFactory;
private readonly IHttpMessageFactory messageFactory;
public UsersEndpoint(
IHttpClientFactory clientFactory,
IHttpMessageFactory messageFactory)
{
this.clientFactory = clientFactory;
this.messageFactory = messageFactory;
}
public async Task<EndpointResponse<User>> GetUserAsync(
int userId,
CancellationToken cancellationToken = default)
{
var client = clientFactory.CreateClient("MyApiClient");
var requestBuilder = messageFactory.FromTemplate("/api/users/{userId}");
requestBuilder.WithPathParameter("userId", userId);
using var request = requestBuilder.Build(HttpMethod.Get);
using var response = await client.SendAsync(request, cancellationToken);
var responseBuilder = messageFactory.FromResponse(response);
responseBuilder.AddSuccessResponse<User>(HttpStatusCode.OK);
responseBuilder.AddErrorResponse<ProblemDetails>(HttpStatusCode.NotFound);
return await responseBuilder.BuildResponseAsync<User>(cancellationToken);
}
}
Register the endpoint:
services.AddSingleton<IUsersEndpoint, UsersEndpoint>();
Usage Examples
Simple GET Request
var requestBuilder = messageFactory.FromTemplate("/api/products");
using var request = requestBuilder.Build(HttpMethod.Get);
using var response = await client.SendAsync(request, cancellationToken);
var responseBuilder = messageFactory.FromResponse(response);
responseBuilder.AddSuccessResponse<List<Product>>(HttpStatusCode.OK);
var result = await responseBuilder.BuildResponseAsync<List<Product>>(cancellationToken);
if (result.IsSuccess)
{
var products = result.OkContent;
// Process products
}
POST Request with Body
var newUser = new CreateUserRequest
{
Name = "John Doe",
Email = "john@example.com"
};
var requestBuilder = messageFactory.FromTemplate("/api/users");
requestBuilder.WithBody(newUser);
using var request = requestBuilder.Build(HttpMethod.Post);
using var response = await client.SendAsync(request, cancellationToken);
var responseBuilder = messageFactory.FromResponse(response);
responseBuilder.AddSuccessResponse<User>(HttpStatusCode.Created);
responseBuilder.AddErrorResponse<ValidationProblemDetails>(HttpStatusCode.BadRequest);
var result = await responseBuilder.BuildResponseAsync<User>(cancellationToken);
Using Path and Query Parameters
var requestBuilder = messageFactory.FromTemplate("/api/users/{userId}/posts");
requestBuilder.WithPathParameter("userId", 123);
requestBuilder.WithQueryParameter("pageSize", 10);
requestBuilder.WithQueryParameter("page", 1);
requestBuilder.WithQueryParameter("orderBy", "createdDate");
using var request = requestBuilder.Build(HttpMethod.Get);
// Results in: GET /api/users/123/posts?pageSize=10&page=1&orderBy=createdDate
Handling Responses
Success and Error Response Handling
var responseBuilder = messageFactory.FromResponse(response);
responseBuilder.AddSuccessResponse<User>(HttpStatusCode.OK);
responseBuilder.AddErrorResponse<ProblemDetails>(HttpStatusCode.BadRequest);
responseBuilder.AddErrorResponse<ProblemDetails>(HttpStatusCode.NotFound);
var result = await responseBuilder.BuildResponseAsync<User, ProblemDetails>(cancellationToken);
if (result.IsOk)
{
var user = result.OkContent;
Console.WriteLine($"Success: {user.Name}");
}
else if (result.IsBadRequest)
{
var problem = result.BadRequestContent;
Console.WriteLine($"Validation Error: {problem.Detail}");
}
else if (result.IsNotFound)
{
Console.WriteLine("User not found");
}
Custom Response Processing
var responseBuilder = messageFactory.FromResponse(response);
responseBuilder.AddSuccessResponse<User>(HttpStatusCode.OK);
var result = await responseBuilder.BuildResponseAsync(
response => new CustomResult
{
Success = response.IsSuccess,
StatusCode = response.StatusCode,
User = response.ContentObject as User
},
cancellationToken);
Best Practices
Choosing Between Overloads
| Scenario | Recommended Approach |
|---|---|
| Simple HTTP client with just base URL and timeout | Non-generic overload (AddAtcRestClient(string, Uri, TimeSpan)) |
| Additional configuration properties needed | Generic overload with custom options type |
Multiple Client Registration
When registering multiple HTTP clients, consider using a consistent naming convention:
// Good: Clear, distinct names
services.AddAtcRestClient("Users-API", new Uri("https://users.api.com"), TimeSpan.FromSeconds(30));
services.AddAtcRestClient("Orders-API", new Uri("https://orders.api.com"), TimeSpan.FromSeconds(60));
services.AddAtcRestClient("Payments-API", new Uri("https://payments.api.com"), TimeSpan.FromSeconds(45));
API Reference
Core Types
AddAtcRestClient Extension Methods
// Non-generic overload for simple scenarios
IServiceCollection AddAtcRestClient(
string clientName,
Uri baseAddress,
TimeSpan timeout,
Action<IHttpClientBuilder>? httpClientBuilder = null,
IContractSerializer? contractSerializer = null)
// Generic overload for typed options
IServiceCollection AddAtcRestClient<TOptions>(
string clientName,
TOptions options,
Action<IHttpClientBuilder>? httpClientBuilder = null,
IContractSerializer? contractSerializer = null)
where TOptions : AtcRestClientOptions, new()
AtcRestClientOptions
public class AtcRestClientOptions
{
public virtual Uri? BaseAddress { get; set; }
public virtual TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(30);
}
IHttpMessageFactory
public interface IHttpMessageFactory
{
IMessageRequestBuilder FromTemplate(string pathTemplate);
IMessageResponseBuilder FromResponse(HttpResponseMessage? response);
}
IMessageRequestBuilder
public interface IMessageRequestBuilder
{
IMessageRequestBuilder WithPathParameter(string name, object? value);
IMessageRequestBuilder WithQueryParameter(string name, object? value);
IMessageRequestBuilder WithHeaderParameter(string name, object? value);
IMessageRequestBuilder WithBody<TBody>(TBody body);
HttpRequestMessage Build(HttpMethod method);
}
IMessageResponseBuilder
public interface IMessageResponseBuilder
{
IMessageResponseBuilder AddSuccessResponse(HttpStatusCode statusCode);
IMessageResponseBuilder AddSuccessResponse<TResponseContent>(HttpStatusCode statusCode);
IMessageResponseBuilder AddErrorResponse(HttpStatusCode statusCode);
IMessageResponseBuilder AddErrorResponse<TResponseContent>(HttpStatusCode statusCode);
Task<TResult> BuildResponseAsync<TResult>(
Func<EndpointResponse, TResult> factory,
CancellationToken cancellationToken);
Task<EndpointResponse<TSuccessContent>> BuildResponseAsync<TSuccessContent>(
CancellationToken cancellationToken)
where TSuccessContent : class;
Task<EndpointResponse<TSuccessContent, TErrorContent>> BuildResponseAsync<TSuccessContent, TErrorContent>(
CancellationToken cancellationToken)
where TSuccessContent : class
where TErrorContent : class;
}
EndpointResponse
public class EndpointResponse : IEndpointResponse
{
public bool IsSuccess { get; }
public HttpStatusCode StatusCode { get; }
public string Content { get; }
public object? ContentObject { get; }
public IReadOnlyDictionary<string, IEnumerable<string>> Headers { get; }
}
// Generic variants available:
// - EndpointResponse<TSuccess>
// - EndpointResponse<TSuccess, TError>
How to Contribute
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.AspNetCore.Http (>= 2.3.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.10)
- Microsoft.Extensions.Http (>= 9.0.10)
- Microsoft.Extensions.Options (>= 9.0.10)
- System.Text.Json (>= 9.0.10)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Atc.Rest.Client:
| Package | Downloads |
|---|---|
|
Atc.Rest.ApiGenerator
Atc.Rest.ApiGenerator is a WebApi C# code generator using a OpenApi 3.0.x specification YAML file. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.12 | 277 | 12/7/2025 |
| 2.0.11 | 202 | 12/4/2025 |
| 2.0.10 | 202 | 12/4/2025 |
| 2.0.1 | 427 | 11/10/2025 |
| 1.0.84 | 3,355 | 12/17/2024 |
| 1.0.79 | 4,172 | 7/14/2024 |
| 1.0.74 | 300 | 6/28/2024 |
| 1.0.69 | 276 | 5/8/2024 |
| 1.0.55 | 3,871 | 7/5/2023 |
| 1.0.53 | 6,838 | 6/9/2023 |
| 1.0.48 | 12,910 | 2/2/2023 |
| 1.0.36 | 14,812 | 1/24/2022 |
| 1.0.31 | 4,523 | 11/7/2021 |
| 1.0.29 | 11,254 | 2/3/2021 |
| 1.0.25 | 593 | 2/2/2021 |