CommonNetFuncs.Web.Requests 4.0.49

There is a newer version of this package available.
See the version list below for details.
dotnet add package CommonNetFuncs.Web.Requests --version 4.0.49
                    
NuGet\Install-Package CommonNetFuncs.Web.Requests -Version 4.0.49
                    
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="CommonNetFuncs.Web.Requests" Version="4.0.49" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CommonNetFuncs.Web.Requests" Version="4.0.49" />
                    
Directory.Packages.props
<PackageReference Include="CommonNetFuncs.Web.Requests" />
                    
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 CommonNetFuncs.Web.Requests --version 4.0.49
                    
#r "nuget: CommonNetFuncs.Web.Requests, 4.0.49"
                    
#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 CommonNetFuncs.Web.Requests@4.0.49
                    
#: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=CommonNetFuncs.Web.Requests&version=4.0.49
                    
Install as a Cake Addin
#tool nuget:?package=CommonNetFuncs.Web.Requests&version=4.0.49
                    
Install as a Cake Tool

CommonNetFuncs.Web.Requests

License NuGet Version nuget

This lightweight project contains helper methods for several common functions required by applications.

Contents


RestHelpers

A generic HTTP client wrapper that sends typed REST requests and deserializes responses. Built on a long-lived SocketsHttpHandler-backed HttpClient with configurable keep-alive, per-request bearer tokens, custom headers, timeouts, and optional MessagePack serialization. All requests are made via a RequestOptions<TBody> configuration object so callers never construct HttpRequestMessage by hand.

RestHelpers Usage Examples

<details> <summary><h3>Usage Examples</h3></summary>

RestRequest

Sends a request and returns a deserialized response, or null on failure.

using CommonNetFuncs.Web.Requests.Rest;

RestHelpers rest = new();

MyResponse? response = await rest.RestRequest<MyResponse, MyBody>(
    new RequestOptions<MyBody>
    {
        Url = "https://api.example.com/items",
        HttpMethod = HttpMethod.Post,
        BodyObject = new MyBody { Name = "Widget" },
        BearerToken = "my-token",
        Timeout = 30, // seconds
    }
);
StreamingRestRequest

Streams a newline-delimited JSON (NDJSON) response as an IAsyncEnumerable<T>, useful for large or server-sent data sets.

await foreach (MyItem? item in rest.StreamingRestRequest<MyItem, object?>(
    new RequestOptions<object?> { Url = "https://api.example.com/stream", HttpMethod = HttpMethod.Get }))
{
    if (item is not null) Process(item);
}
RestRequestObject

Returns a RestObject<TResponse> wrapping both the deserialized response and the raw HttpResponseMessage, giving access to status codes and headers.

RestObject<MyResponse> result = await rest.RestRequestObject<MyResponse, object?>(
    new RequestOptions<object?> { Url = "https://api.example.com/items/1", HttpMethod = HttpMethod.Get }
);

if (result.Response?.IsSuccessStatusCode == true)
{
    MyResponse? data = result.Result;
}

</details>


RestHelpersWrapper

A higher-level HTTP client facade built on top of RestHelpers. It adds automatic retry/resilience logic, bearer token management (including automatic refresh on 401/403), and support for a shared RestHelperOptionsDefaultConfig that applies common settings across all calls made through the same wrapper instance.

RestHelpersWrapper Usage Examples

<details> <summary><h3>Usage Examples</h3></summary>

Basic Usage

Make typed HTTP calls with built-in retry and resilience without manually constructing HttpRequestMessage.

using CommonNetFuncs.Web.Requests.Rest.Options;
using CommonNetFuncs.Web.Requests.Rest.RestHelperWrapper;

RestHelpersWrapper wrapper = new(restClientFactory);

// GET
MyResponse? item = await wrapper.Get<MyResponse>(
    new RestHelperOptions("api/items/1", "MyApi",
        ResilienceOptions: new ResilienceOptions(MaxRetry: 3, RetryDelay: 500)));

// POST
MyResponse? created = await wrapper.PostRequest(
    new RestHelperOptions("api/items", "MyApi"),
    new MyRequest { Name = "Widget" });

// PATCH (diffs old vs new and sends only changed fields)
MyResponse? updated = await wrapper.PatchRequest(
    new RestHelperOptions("api/items/1", "MyApi"), newModel, oldModel);

// DELETE
MyResponse? deleted = await wrapper.DeleteRequest<MyResponse>(
    new RestHelperOptions("api/items/1", "MyApi"));
RestHelperOptionsDefaultConfig

RestHelperOptionsDefaultConfig lets you define fallback values applied to every call made through a RestHelpersWrapper instance. Per-call options always take precedence; defaults only fill in what is null on the per-call RestHelperOptions (except UseBearerToken, which always overrides when non-null).

Property Behavior
UseBearerToken When non-null, always overrides the per-call value
ResilienceOptions.GetBearerTokenFunc Fills in if the per-call options has no GetBearerTokenFunc
JsonSerializerOptions Fills in if null on the per-call options
MsgPackOptions Fills in if null on the per-call options
CompressionOptions Fills in if null on the per-call options
using CommonNetFuncs.Web.Requests;
using CommonNetFuncs.Web.Requests.Rest.Options;
using CommonNetFuncs.Web.Requests.Rest.RestHelperWrapper;

RestHelperOptionsDefaultConfig defaultConfig = new()
{
    // Always enforce bearer token auth for every call through this wrapper.
    // When non-null, overrides the per-call UseBearerToken value.
    UseBearerToken = true,

    // Token retrieval function. Receives the API name and a flag indicating whether
    // a forced refresh is required (set automatically after a 401/403 response).
    ResilienceOptions = new ResilienceOptions(
        MaxRetry: 3,
        RetryDelay: 500,
        GetBearerTokenFunc: async (apiName, forceRefresh) =>
            await tokenProvider.GetTokenAsync(apiName, forceRefresh)
    ),

    // Default JSON options applied when not specified per call
    JsonSerializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true },

    // Default compression applied when not specified per call
    CompressionOptions = new CompressionOptions(UseCompression: true, CompressionType: ECompressionType.Gzip)
};

RestHelpersWrapper wrapper = new(restClientFactory, defaultConfig);

// Auth, serializer, and compression settings are applied automatically -
// no need to repeat them on every call.
MyResponse? result = await wrapper.Get<MyResponse>(new RestHelperOptions("api/items", "MyApi"));
Dependency Injection Setup

Register RestHelperOptionsDefaultConfig as a singleton. The DI container automatically injects it into RestHelpersWrapper via its two-parameter constructor when present; without it, the single-parameter constructor is used and no defaults are applied.

using CommonNetFuncs.Web.Requests.Rest.Options;
using CommonNetFuncs.Web.Requests.Rest.RestHelperWrapper;

// In Program.cs / Startup.cs

// 1. Register your token provider (if using bearer token auth)
builder.Services.AddSingleton<ITokenProvider, MyTokenProvider>();

// 2. Register the default config, resolving dependencies from the container
builder.Services.AddSingleton(sp =>
{
    ITokenProvider tokenProvider = sp.GetRequiredService<ITokenProvider>();
    return new RestHelperOptionsDefaultConfig
    {
        UseBearerToken = true,
        ResilienceOptions = new ResilienceOptions(
            MaxRetry: 3,
            RetryDelay: 500,
            GetBearerTokenFunc: (apiName, forceRefresh) =>
                tokenProvider.GetTokenAsync(apiName, forceRefresh)
        ),
        JsonSerializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
    };
});

// 3. Register the named HttpClient, IRestClientFactory, and RestHelpersWrapper
builder.Services.AddRestClient("MyApi", client =>
    client.BaseAddress = new Uri("https://api.example.com/"));

// 4. Inject RestHelpersWrapper wherever needed
public class MyService(RestHelpersWrapper wrapper)
{
    public async Task<MyResponse?> GetItemAsync(int id) =>
        await wrapper.Get<MyResponse>(new RestHelperOptions($"api/items/{id}", "MyApi"));

    public async Task<MyResponse?> CreateItemAsync(MyRequest request) =>
        await wrapper.PostRequest(new RestHelperOptions("api/items", "MyApi"), request);
}

Tip: When only sharing serializer or compression defaults without authentication, omit UseBearerToken (or leave it null) and no bearer token logic is applied.

</details>


PatchCreator

Creates a Newtonsoft.Json JsonPatchDocument by diffing two objects of the same type. Compares property values and generates add, remove, and replace operations for every changed field, including nested objects.

PatchCreator Usage Examples

<details> <summary><h3>Usage Examples</h3></summary>

CreatePatch
using CommonNetFuncs.Web.Requests;
using Microsoft.AspNetCore.JsonPatch;

MyEntity original = await GetFromDb(id);
MyEntity modified = original with { Name = "New Name", Price = 9.99m };

JsonPatchDocument patch = PatchCreator.CreatePatch(original, modified);
// patch.Operations => [ { op: "replace", path: "/Name", value: "New Name" }, { op: "replace", path: "/Price", value: 9.99 } ]

// Send via REST
await rest.RestRequest<MyEntity, HttpContent>(
    new RequestOptions<HttpContent>
    {
        Url = $"https://api.example.com/items/{id}",
        HttpMethod = HttpMethod.Patch,
        PatchDocument = patch.ToStringContent(),
    }
);

</details>


DistributedCacheExtensions

Generic IDistributedCache extension methods for storing and retrieving strongly-typed objects serialized with System.Text.Json.

DistributedCacheExtensions Usage Examples

<details> <summary><h3>Usage Examples</h3></summary>

using CommonNetFuncs.Web.Requests;

// Store
await cache.SetAsync("user:42", myUser, new DistributedCacheEntryOptions
{
    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
});

// Retrieve synchronously
if (cache.TryGetValue("user:42", out MyUser? user))
{
    // cache hit
}

// Retrieve asynchronously
MyUser? user = await cache.TryGetValueAsync<MyUser>("user:42");

</details>


JsonPatchFormatter

Provides a pre-configured NewtonsoftJsonPatchInputFormatter for use with MVC controller-based APIs that accept JsonPatchDocument<T> as a request body. Insert it as the first input formatter so Newtonsoft.Json handles JSON Patch deserialization while the rest of the pipeline uses System.Text.Json.

JsonPatchFormatter Usage Examples

<details> <summary><h3>Usage Examples</h3></summary>

using CommonNetFuncs.Web.Requests;

builder.Services.AddControllers(options =>
{
    options.InputFormatters.Insert(0, JsonPatchFormatter.JsonPatchInputFormatter());
});

</details>

Installation

Install via NuGet:

dotnet add package CommonNetFuncs.Web.Requests

License

This project is licensed under the MIT License - see the LICENSE file for details.

Product 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. 
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
4.0.56 55 6/2/2026
4.0.53 98 5/28/2026
4.0.49 97 5/24/2026
4.0.48 96 5/24/2026
4.0.43 104 5/14/2026
4.0.40 107 5/10/2026
4.0.39 115 5/10/2026
4.0.37 104 5/9/2026
4.0.36 102 5/8/2026
4.0.33 124 4/23/2026
4.0.31 106 4/21/2026
4.0.30 106 4/23/2026
4.0.29 105 4/20/2026
4.0.28 105 4/19/2026
4.0.27 118 4/15/2026
4.0.25 118 4/3/2026
4.0.23 111 3/30/2026
3.8.44 116 3/13/2026
Loading failed