A powerful and intuitive HTTP client library for .NET. Write HTTP requests with a clean, modern API that feels natural and easy to use.
// Simple and clean
var response = await Nexar.Get<User>("https://api.example.com/users/1");
Console.WriteLine(response.Data.Name);- Static Methods:
Nexar.Get(),Nexar.Post(),Nexar.Put(),Nexar.Delete(), etc. - Instance Creation:
Nexar.Create()for custom configurations - Typed Responses:
response.Data,response.Status,response.Headers - Request Configuration: Flexible request options
- Interceptors: Request and response interceptors
- Automatic JSON: Serialization and deserialization
- Retry Mechanism: Exponential backoff support
- Authentication: Bearer tokens, Basic Auth, API keys
- Fluent API: Chainable request builder
- Backward Compatible: Legacy API still works
dotnet add package BuzzSpire.Nexar// Option 1: Simple string response (no generic type needed)
string response = await Nexar.Get("https://api.example.com/users/1");
Console.WriteLine(response); // Raw JSON string
// Option 2: Typed response with automatic deserialization
var response = await Nexar.Get<User>("https://api.example.com/users/1");
if (response.IsSuccess)
{
Console.WriteLine(response.Data.Name);
Console.WriteLine($"Status: {response.Status}"); // 200
}
// POST - also works both ways
string rawResponse = await Nexar.Post("/users", new { Name = "John" });
var typedResponse = await Nexar.Post<User>("/users", new { Name = "John" });
// All methods support both versions
await Nexar.Put("/users/1", updatedData); // Returns string
await Nexar.Put<User>("/users/1", updatedData); // Returns NexarResponse<User>
await Nexar.Delete("/users/1"); // Returns string
await Nexar.Delete<object>("/users/1"); // Returns NexarResponse<object>// Create an instance with custom configuration
var api = Nexar.Create(new NexarConfig
{
BaseUrl = "https://api.example.com",
DefaultHeaders = new Dictionary<string, string>
{
{ "Accept", "application/json" },
{ "User-Agent", "MyApp/1.0" }
},
TimeoutSeconds = 30,
MaxRetryAttempts = 3
});
// Now use relative URLs
var user = await api.GetAsync<User>("/users/1");// Full request configuration
var response = await Nexar.Request<User>(new RequestOptions
{
Method = "GET",
Url = "https://api.example.com/users/1",
Headers = new Dictionary<string, string>
{
{ "Authorization", "Bearer token" }
},
Timeout = 5000
});var response = await Nexar.Get<User>("/users/1");
// Access response properties
Console.WriteLine(response.Data); // The deserialized object
Console.WriteLine(response.Status); // 200
Console.WriteLine(response.StatusText); // "OK"
Console.WriteLine(response.Headers); // Response headers
Console.WriteLine(response.IsSuccess); // true/false// Simple - just get the JSON string
string json = await Nexar.Get("https://api.example.com/users/1");
Console.WriteLine(json);
// Typed - automatic deserialization
var response = await Nexar.Get<User>("https://api.example.com/users/1");
Console.WriteLine(response.Data.Name);
Console.WriteLine(response.Status);var response = await Nexar.Post<User>("/users", new {
Name = "John",
Email = "[email protected]"
});
if (response.IsSuccess)
{
Console.WriteLine($"Created user: {response.Data.Id}");
}var api = Nexar.Create(new NexarConfig {
BaseUrl = "https://api.example.com",
TimeoutSeconds = 5,
DefaultHeaders = new Dictionary<string, string> {
{ "Authorization", "Bearer token" }
}
});
var response = await api.GetAsync<User>("/users/1");var response = await Nexar.Request<User>(new RequestOptions {
Method = "POST",
Url = "/users",
Data = new { Name = "John" },
Headers = new Dictionary<string, string> {
{ "Content-Type", "application/json" }
}
});public class LoggingInterceptor : IInterceptor
{
public async Task<HttpRequestMessage> OnRequestAsync(HttpRequestMessage request)
{
Console.WriteLine($"→ {request.Method} {request.RequestUri}");
return request;
}
public async Task<HttpResponseMessage> OnResponseAsync(HttpResponseMessage response)
{
Console.WriteLine($"← {response.StatusCode}");
return response;
}
public async Task OnErrorAsync(Exception exception)
{
Console.WriteLine($"✗ {exception.Message}");
}
}
var api = Nexar.Create();
api.Interceptors.Add(new LoggingInterceptor());// Bearer Token
var api = Nexar.Create();
var response = await api.Request()
.Url("/protected")
.WithBearerToken("your-jwt-token")
.GetAsync<Data>();
// Basic Auth
var response = await api.Request()
.Url("/protected")
.WithBasicAuth("username", "password")
.GetAsync<Data>();
// API Key
var response = await api.Request()
.Url("/protected")
.WithApiKey("X-API-Key", "your-key")
.GetAsync<Data>();var response = await Nexar.Create()
.Request()
.Url("https://api.example.com/search")
.WithHeader("Accept", "application/json")
.WithQuery("q", "nexar")
.WithQuery("limit", 10)
.GetAsync<SearchResults>();var response = await api.Request()
.Url("/users")
.WithQuery("page", 1)
.WithQuery("limit", 20)
.WithQuery("sort", "name")
.GetAsync<List<User>>();
// Generates: /users?page=1&limit=20&sort=namevar api = Nexar.Create(new NexarConfig
{
MaxRetryAttempts = 3,
RetryDelayMilliseconds = 1000,
UseExponentialBackoff = true // 1s, 2s, 4s
});Each method has two versions:
Simple (returns string):
Nexar.Get(url, options?)- GET request, returns raw stringNexar.Post(url, data?, options?)- POST request, returns raw stringNexar.Put(url, data?, options?)- PUT request, returns raw stringNexar.Delete(url, options?)- DELETE request, returns raw stringNexar.Patch(url, data?, options?)- PATCH request, returns raw stringNexar.Head(url, options?)- HEAD request, returns raw string
Typed (returns NexarResponse<T>):
Nexar.Get<T>(url, options?)- GET with typed responseNexar.Post<T>(url, data?, options?)- POST with typed responseNexar.Put<T>(url, data?, options?)- PUT with typed responseNexar.Delete<T>(url, options?)- DELETE with typed responseNexar.Patch<T>(url, data?, options?)- PATCH with typed responseNexar.Head<T>(url, options?)- HEAD with typed response
Advanced:
Nexar.Request<T>(options)- Request with full config
Nexar.Create()- Create instance with default configNexar.Create(NexarConfig)- Create instance with custom configNexar.Create(RequestOptions)- Create instance from request options
response.Data- Deserialized response dataresponse.Status- HTTP status code (int)response.StatusText- Status messageresponse.Headers- Response headersresponse.IsSuccess- Success indicatorresponse.Config- Request configuration usedresponse.RawContent- Raw response string
new NexarConfig
{
BaseUrl = "https://api.example.com",
DefaultHeaders = new Dictionary<string, string>(),
TimeoutSeconds = 100,
MaxRetryAttempts = 0,
RetryDelayMilliseconds = 1000,
UseExponentialBackoff = true,
ValidateSslCertificates = true
}new RequestOptions
{
Url = "/users",
Method = "GET",
Headers = new Dictionary<string, string>(),
Params = new Dictionary<string, string>(), // Query params
Data = new { }, // Request body
Timeout = 5000,
BaseURL = "https://api.example.com",
MaxRetries = 3
}// Quickest way to make a request
var data = await Nexar.Get<User>("/users/1");// Create a configured instance for multiple requests
var api = Nexar.Create(new NexarConfig
{
BaseUrl = "https://api.example.com"
});
var user = await api.GetAsync<User>("/users/1");
var posts = await api.GetAsync<List<Post>>("/posts");var response = await Nexar.Get<User>("/users/1");
if (response.IsSuccess)
{
Console.WriteLine($"User: {response.Data.Name}");
}
else
{
Console.WriteLine($"Error {response.Status}: {response.ErrorMessage}");
}Check out the samples directory for complete working examples including:
- Static method usage
- Instance creation
- Request configuration
- Response handling
- Authentication
- Interceptors
- Retry mechanism
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.
Made with ❤️ for .NET developers