Fuzn.FluentHttp 0.0.5-beta

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

Fuzn.FluentHttp

A lightweight fluent API for building and sending HTTP requests with HttpClient. Provides a clean, chainable interface for configuring URLs, headers, content types, authentication, and serialization.

Installation

dotnet add package Fuzn.FluentHttp

Quick Start

using Fuzn.FluentHttp;

var httpClient = new HttpClient();

// Simple GET request with typed response
var response = await httpClient
    .Url("https://api.example.com/users/1")
    .Get<User>();

if (response.IsSuccessful)
{
    Console.WriteLine(response.Data!.Name);
}

Features

Typed Responses

Use generic HTTP methods to get strongly-typed responses:

var response = await httpClient.Url("/api/users/1").Get<User>();

if (response.IsSuccessful)
{
    User user = response.Data!;
}
else
{
    Console.WriteLine($"Error {response.StatusCode}: {response.Body}");
}

HTTP Methods

All standard HTTP methods are supported, with both generic and non-generic versions:

// Non-generic (returns HttpResponse)
await httpClient.Url("/api/resource").Get();
await httpClient.Url("/api/resource").Post();
await httpClient.Url("/api/resource").Put();
await httpClient.Url("/api/resource").Patch();
await httpClient.Url("/api/resource").Delete();
await httpClient.Url("/api/resource").Head();
await httpClient.Url("/api/resource").Options();

// Generic (returns HttpResponse<T>)
await httpClient.Url("/api/resource").Get<MyType>();
await httpClient.Url("/api/resource").Post<MyType>();
await httpClient.Url("/api/resource").Put<MyType>();
await httpClient.Url("/api/resource").Patch<MyType>();
await httpClient.Url("/api/resource").Delete<MyType>();

Request Body

var response = await httpClient
    .Url("https://api.example.com/users")
    .Body(new { Name = "John", Email = "john@example.com" })
    .Post<User>();

Query Parameters

// Single parameter
var response = await httpClient
    .Url("https://api.example.com/search")
    .QueryParam("q", "dotnet")
    .QueryParam("page", 1)
    .Get<SearchResult>();

// Multiple parameters via dictionary
var response = await httpClient
    .Url("https://api.example.com/search")
    .QueryParams(new Dictionary<string, object?> 
    { 
        ["q"] = "dotnet", 
        ["page"] = 1 
    })
    .Get<SearchResult>();

// Anonymous object
var response = await httpClient
    .Url("https://api.example.com/search")
    .QueryParams(new { q = "dotnet", page = 1 })
    .Get<SearchResult>();

// Multiple values for same parameter
var response = await httpClient
    .Url("https://api.example.com/items")
    .QueryParam("tags", new[] { "c#", "dotnet", "http" })
    .Get<ItemList>();

Headers

var response = await httpClient
    .Url("https://api.example.com/data")
    .Header("X-Custom-Header", "value")
    .Headers(new Dictionary<string, string> 
    { 
        ["X-Another"] = "another-value" 
    })
    .Get<Data>();

Authentication

// Bearer token
var response = await httpClient
    .Url("https://api.example.com/protected")
    .AuthBearer("your-jwt-token")
    .Get<ProtectedData>();

// Basic authentication
var response = await httpClient
    .Url("https://api.example.com/protected")
    .AuthBasic("username", "password")
    .Get<ProtectedData>();

// API Key
var response = await httpClient
    .Url("https://api.example.com/protected")
    .AuthApiKey("your-api-key")
    .Get<ProtectedData>();

// Custom header name for API key
var response = await httpClient
    .Url("https://api.example.com/protected")
    .AuthApiKey("your-api-key", "Authorization")
    .Get<ProtectedData>();

Content Types

var response = await httpClient
    .Url("https://api.example.com/data")
    .ContentType(ContentTypes.Json)
    .Body(data)
    .Post<Result>();

// Custom content type
var response = await httpClient
    .Url("https://api.example.com/graphql")
    .ContentType("application/graphql")
    .Body(query)
    .Post<GraphQLResponse>();

Accept Headers

var response = await httpClient
    .Url("https://api.example.com/data")
    .Accept(AcceptTypes.Json)
    .Get<Data>();

// Custom accept type
var response = await httpClient
    .Url("https://api.example.com/report")
    .Accept("application/pdf")
    .Get();

File Uploads

// Upload file from stream
var response = await httpClient
    .Url("https://api.example.com/upload")
    .File("file", "document.pdf", fileStream, "application/pdf")
    .Post<UploadResult>();

// Upload file from byte array
var response = await httpClient
    .Url("https://api.example.com/upload")
    .File("file", "image.png", imageBytes, "image/png")
    .Post<UploadResult>();

// Multiple files with form fields
var response = await httpClient
    .Url("https://api.example.com/upload")
    .File("file1", "doc1.pdf", stream1)
    .File("file2", "doc2.pdf", stream2)
    .FormField("description", "My documents")
    .Post<UploadResult>();

Cookies

var response = await httpClient
    .Url("https://api.example.com/data")
    .Cookie("session", "abc123")
    .Cookie("preference", "dark-mode", path: "/", duration: TimeSpan.FromDays(30))
    .Get<Data>();

Timeouts

var response = await httpClient
    .Url("https://api.example.com/slow-endpoint")
    .Timeout(TimeSpan.FromSeconds(30))
    .Get<Data>();

Custom User-Agent

var response = await httpClient
    .Url("https://api.example.com/data")
    .UserAgent("MyApp/1.0")
    .Get<Data>();

Working with Responses

HttpResponse

var response = await httpClient
    .Url("https://api.example.com/users/1")
    .Get();

// Check if successful (2xx status code)
if (response.IsSuccessful)
{
    // Deserialize to type
    var user = response.As<User>();
    
    // Get raw body
    string body = response.Body;
    
    // Get as bytes
    byte[] bytes = response.AsBytes();
}

// Access status code
HttpStatusCode status = response.StatusCode;

// Access headers
var headers = response.Headers;
var contentHeaders = response.ContentHeaders;

// Access cookies
var cookies = response.Cookies;

HttpResponse<T>

var response = await httpClient
    .Url("https://api.example.com/users/1")
    .Get<User>();

// Typed data (auto-deserialized)
User? user = response.Data;

// Check success
bool success = response.IsSuccessful;

// Status code
HttpStatusCode status = response.StatusCode;

// Raw body
string body = response.Body;

// Headers and cookies
var headers = response.Headers;
var cookies = response.Cookies;

// Deserialize to a different type
var error = response.As<ProblemDetails>();

Custom Serialization

Implement ISerializerProvider to use your preferred serializer:

public class NewtonsoftSerializerProvider : ISerializerProvider
{
    public string Serialize<T>(T obj) => 
        JsonConvert.SerializeObject(obj);

    public T? Deserialize<T>(string json) => 
        JsonConvert.DeserializeObject<T>(json);
}

// Use custom serializer
var response = await httpClient
    .Url("https://api.example.com/data")
    .SerializerProvider(new NewtonsoftSerializerProvider())
    .Body(data)
    .Post<Result>();

Cancellation Support

All HTTP methods support cancellation tokens:

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));

var response = await httpClient
    .Url("https://api.example.com/data")
    .Get<Data>(cts.Token);

You can also set a cancellation token on the builder, which will be linked with any token passed to the HTTP method:

var builderCts = new CancellationTokenSource();
var methodCts = new CancellationTokenSource(TimeSpan.FromSeconds(10));

// Both tokens are linked - cancelling either will cancel the request
var response = await httpClient
    .Url("https://api.example.com/data")
    .CancellationToken(builderCts.Token)
    .Get<Data>(methodCts.Token);

License

MIT License - see LICENSE 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.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Fuzn.FluentHttp:

Package Downloads
Fuzn.TestFuzn.Plugins.Http

Http plugin for TestFuzn

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.6.8-beta 385 2/13/2026
0.6.7-beta 51 2/12/2026
0.6.6-beta 55 2/9/2026
0.6.5-beta 49 2/9/2026
0.6.4-beta 52 2/8/2026
0.6.3-beta 48 2/4/2026
0.6.2-beta 47 2/4/2026
0.6.1-beta 46 2/3/2026
0.6.0-beta 50 2/1/2026
0.0.11-beta 49 1/30/2026
0.0.10-beta 45 1/30/2026
0.0.9-beta 85 1/30/2026
0.0.8-beta 50 1/30/2026
0.0.7-beta 50 1/29/2026
0.0.6-beta 49 1/29/2026
0.0.5-beta 56 1/26/2026
0.0.4-beta 55 1/26/2026
0.0.3-beta 53 1/25/2026