DSeries.DHttpClient.Core
1.0.4
See the version list below for details.
dotnet add package DSeries.DHttpClient.Core --version 1.0.4
NuGet\Install-Package DSeries.DHttpClient.Core -Version 1.0.4
<PackageReference Include="DSeries.DHttpClient.Core" Version="1.0.4" />
<PackageVersion Include="DSeries.DHttpClient.Core" Version="1.0.4" />
<PackageReference Include="DSeries.DHttpClient.Core" />
paket add DSeries.DHttpClient.Core --version 1.0.4
#r "nuget: DSeries.DHttpClient.Core, 1.0.4"
#:package DSeries.DHttpClient.Core@1.0.4
#addin nuget:?package=DSeries.DHttpClient.Core&version=1.0.4
#tool nuget:?package=DSeries.DHttpClient.Core&version=1.0.4
DHttpClient - A Fluent HTTP Request Builder for .NET
DHttpClient is a flexible and fluent HTTP request builder for .NET applications. It simplifies making HTTP requests by providing an intuitive API for configuring requests, handling responses, and managing various content types.
Features
- Fluent API: Easily build HTTP requests with a chainable, readable syntax.
- Supports All HTTP Methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS.
- Flexible Content Handling:
- JSON serialization and deserialization
- Form URL-encoded content
- Multipart form-data for file uploads
- Automatic Query Parameter Handling
- Customizable Headers and Timeout Settings
- Error Handling with Unified Response Wrapper
- Supports Custom HttpClient for DI compatibility
- Result<T> Wrapper for uniform success/error handling
- Stream and Byte Array Support for file downloads
- Custom HTTP Headers for Requests and Content
- Supports Multipart Requests for handling multiple parts of data
- Custom HTTP Timeout Configuration
Installation
Add the package reference to your .NET project:
Install-Package DHttpClient
Or, using .NET CLI:
dotnet add package DHttpClient
Usage
Basic GET Request
using DHttpClient;
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/get")
.WithMethod(HttpMethod.Get);
var response = await request.SendAsync();
if (response.IsSuccess)
{
var content = await response.Data.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
else
{
Console.WriteLine($"Error: {response.ErrorMessage}");
}
GET Request with Query Parameters
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/get")
.WithQueryParameters(new { user = "JohnDoe", age = 30 })
.WithMethod(HttpMethod.Get);
POST Request with JSON Payload
var payload = new { name = "John", email = "john@example.com" };
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/post")
.WithMethod(HttpMethod.Post)
.WithBodyContent(payload);
POST Request with Form URL-Encoded Content
var formData = new Dictionary<string, string>
{
{ "username", "testuser" },
{ "password", "securepassword" }
};
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/post")
.WithMethod(HttpMethod.Post)
.WithFormUrlEncodedContent(formData);
Multipart Form-Data (File Upload)
var multipartRequest = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/post")
.WithMethod(HttpMethod.Post)
.WithFormMultiPartContent(builder => builder
.AddTextContent("description", "Test file upload")
.AddFileContent("file", File.ReadAllBytes("test.txt"), "test.txt"));
Handling JSON Responses
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/json")
.WithMethod(HttpMethod.Get);
var response = await request.SendObjectAsync<MyResponseModel>();
if (response.IsSuccess)
{
Console.WriteLine(response.Data.SomeProperty);
}
Configuring Headers
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/get")
.WithMethod(HttpMethod.Get)
.WithHeader("Authorization", "Bearer YOUR_TOKEN")
.WithHeader("Custom-Header", "HeaderValue");
Setting Custom Timeout
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/get")
.WithMethod(HttpMethod.Get)
.WithTimeout(TimeSpan.FromSeconds(10));
Using a Custom HttpClient
var httpClient = new HttpClient();
var request = new HttpRequestBuilder(httpClient)
.WithRequestUri("https://httpbin.org/get")
.WithMethod(HttpMethod.Get);
Handling Multipart Requests
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/post")
.WithMethod(HttpMethod.Post)
.WithFormMultiPartContent(builder => builder
.AddTextContent("key", "value")
.AddFileContent("file", File.ReadAllBytes("image.png"), "image.png"));
DHttpClient - Send Functionalities Overview
Sending Requests in DHttpClient
DHttpClient provides multiple methods for sending HTTP requests and handling responses in a structured way using the Result<T>
wrapper.
SendAsync()
Description:
Sends the HTTP request asynchronously and returns the raw HttpResponseMessage
wrapped in a Result<HttpResponseMessage>
.
Usage:
var request = new HttpRequestBuilder()
.WithRequestUri("https://httpbin.org/get")
.WithMethod(HttpMethod.Get);
var result = await request.SendAsync();
if (result.IsSuccess)
{
Console.WriteLine($"Response Status: {result.Data.StatusCode}");
}
else
{
Console.WriteLine($"Error: {result.ErrorMessage}");
}
SendStringAsync()
Description:
Sends the HTTP request and returns the response body as a string
, wrapped in a Result<string>
.
Usage:
var result = await request.SendStringAsync();
if (result.IsSuccess)
{
Console.WriteLine(result.Data); // The raw response content
}
else
{
Console.WriteLine($"Error: {result.ErrorMessage}");
}
SendObjectAsync<T>()
Description:
Sends the HTTP request and deserializes the JSON response to an object of type T
, wrapped in a Result<T>
.
Usage:
public class ApiResponse
{
public string Message { get; set; }
}
var result = await request.SendObjectAsync<ApiResponse>();
if (result.IsSuccess)
{
Console.WriteLine(result.Data.Message); // Access the deserialized object
}
else
{
Console.WriteLine($"Error: {result.ErrorMessage}");
}
SendStreamAsync()
Description:
Sends the request and returns the response content as a Stream
, wrapped in a Result<Stream>
. Useful for downloading large files.
Usage:
var result = await request.SendStreamAsync();
if (result.IsSuccess)
{
using var fileStream = File.Create("downloadedFile.txt");
await result.Data.CopyToAsync(fileStream);
Console.WriteLine("File downloaded successfully.");
}
else
{
Console.WriteLine($"Error: {result.ErrorMessage}");
}
SendBytesAsync()
Description:
Sends the request and returns the response content as a byte[]
, wrapped in a Result<byte[]>
. Useful for handling binary data.
Usage:
var result = await request.SendBytesAsync();
if (result.IsSuccess)
{
File.WriteAllBytes("image.png", result.Data);
Console.WriteLine("Image downloaded successfully.");
}
else
{
Console.WriteLine($"Error: {result.ErrorMessage}");
}
Error Handling
Each method returns a Result<T>
that includes:
IsSuccess
: Indicates if the request was successful.Data
: The response content in the respective format (HttpResponseMessage
,string
,T
,Stream
,byte[]
).ErrorMessage
: Contains error details if the request fails.StatusCode
: The HTTP status code of the response (if available).
Example:
var response = await request.SendStringAsync();
if (!response.IsSuccess)
{
Console.WriteLine($"Error: {response.ErrorMessage}");
}
SendLiveStreamAsync()
Description:
Sends the request expecting a text-based, line-delimited stream (like Server-Sent Events, SSE). Returns a Result<IAsyncEnumerable<string>>
. You must first check Result.IsSuccess
to ensure the stream connection was successfully established before attempting to iterate the stream using await foreach
. The method handles proper resource disposal (ensuring the HttpResponseMessage
and stream are cleaned up).
Usage:
using System.Collections.Generic; // For IAsyncEnumerable
using System.Runtime.CompilerServices; // For [EnumeratorCancellation]
using System.Threading;
using System.Threading.Tasks;
using DHttpClient.Models; // For Result<T>
using System; // For Exception
// Requires System.Linq.Async NuGet package for the WithCancellation extension if desired
// Assuming a builder is configured for a live stream endpoint...
var streamBuilder = new HttpRequestBuilder()
.WithRequestUri("https://your-sse-endpoint.com/stream") // Replace with your stream URL
.WithMethod(HttpMethod.Get); // SSE is typically GET
// Use a CancellationToken source for manual cancellation or timeout
// For timeout, use: using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
using var cts = new CancellationTokenSource();
CancellationToken cancellationToken = cts.Token;
try
{
// Attempt to establish the stream connection
Result<IAsyncEnumerable<string>> liveStreamResult = await streamBuilder.SendLiveStreamAsync(cancellationToken: cancellationToken);
if (liveStreamResult.IsSuccess)
{
Console.WriteLine("Successfully connected to live stream. Reading data...");
// If successful, iterate over the stream using await foreach
// .WithCancellation(cancellationToken) is highly recommended if using a CancellationToken
await foreach (string line in liveStreamResult.Data.WithCancellation(cancellationToken))
{
// Process each received line (the 'data:' prefix is already removed)
Console.WriteLine($"Received: {line}");
// Example: Stop reading based on content
if (line == "END_STREAM")
{
cts.Cancel(); // Request cancellation of the await foreach loop
Console.WriteLine("Received END_STREAM, requesting cancellation.");
}
}
// The await foreach loop exits when the server closes the stream,
// an error occurs, or the CancellationToken is triggered.
Console.WriteLine("Stream iteration finished.");
// Resources (HttpResponseMessage, Stream, Reader) are automatically disposed
// because the IAsyncEnumerable completed or was cancelled.
}
else
{
// Handle failure to establish the stream connection (e.g., 404, 500, network error)
Console.WriteLine($"Error establishing stream: {liveStreamResult.ErrorMessage}");
// Check liveStreamResult.StatusCode for the HTTP status code if available
if (liveStreamResult.StatusCode.HasValue)
{
Console.WriteLine($"HTTP Status: {liveStreamResult.StatusCode.Value}");
}
}
}
catch (OperationCanceledException)
{
// This catch block handles cancellation explicitly triggered via the CancellationToken
Console.WriteLine("Live stream operation was explicitly cancelled (e.g., via CancellationToken).");
}
catch (Exception ex)
{
// This catch block handles unexpected errors that might occur *during* stream reading
// (e.g., connection dropped mid-stream).
Console.WriteLine($"An unexpected error occurred during stream reading: {ex.Message}");
}
These send functionalities provide **structured error handling** and **typed responses**, making HTTP operations in .NET applications more robust and reliable. 🚀
---
## License
This project is licensed under the MIT License.
---
## Contributing
Contributions are welcome! Please open an issue or submit a pull request if you have improvements.
---
## Contact
For questions or issues, open an issue on GitHub.
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 is compatible. 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 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 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 | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | 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.1
- Microsoft.Extensions.Http (>= 9.0.2)
- Newtonsoft.Json (>= 13.0.3)
- System.Text.Json (>= 9.0.4)
-
net8.0
- Microsoft.Extensions.Http (>= 9.0.2)
- Newtonsoft.Json (>= 13.0.3)
- System.Text.Json (>= 9.0.4)
-
net9.0
- Microsoft.Extensions.Http (>= 9.0.2)
- Newtonsoft.Json (>= 13.0.3)
- System.Text.Json (>= 9.0.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Release Notes – DHttpClient Optimizations v1.0.4
We've made some key improvements to how live streaming responses are handled in DHttpClient.
Live Stream Handling Improvements
Consistent Error Handling for Streams: The SendLiveStreamAsync method now aligns with other Send methods by returning a IAsyncEnumerable. This means you can now check for initial connection or header-read failures using the Result object before starting to consume the stream data, providing more robust error detection compared to only relying on exceptions during stream consumption.
Improved Resource Management: The internal logic for SendLiveStreamAsync has been updated to correctly manage the lifetime of the underlying HttpResponseMessage. It ensures the response and its stream are properly disposed of when the async enumerable is fully consumed or the await foreach loop is exited prematurely.
Simplified Data Consumption: For line-delimited stream formats like Server-Sent Events (SSE), SendLiveStreamAsync now automatically strips the data: prefix and leading whitespace from yielded lines, returning only the payload. This simplifies parsing for callers.