Halifax.Http 5.1.0

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

Halifax Service Foundation

Simplistic libraries for complex projects. Halifax eliminates boilerplate in .NET API services — standardized responses, JWT auth, configuration, logging, and more — so you can focus on business logic.

CI

Package NuGet
Halifax.Api NuGet
Halifax.Core NuGet
Halifax.Domain NuGet
Halifax.Http NuGet
Halifax.Excel NuGet

Features

  • Standardized API responses — consistent ApiResponse wrapper for all endpoints
  • Exception handling — throw typed exceptions, get proper HTTP status codes automatically
  • JWT authentication — configure auth in one line, create and validate tokens easily
  • Environment configuration — load .env files, map to strongly-typed classes/records
  • Input validation — fluent Guard helpers for common checks
  • HTTP client base class — typed HttpClient with automatic error mapping
  • OpenAPI + Scalar UI — Swagger docs with interactive API explorer out of the box
  • Logging — Serilog-based structured logging
  • CORS — configurable cross-origin policy
  • Excel/CSV — import and export with column mapping
  • Cryptography — AES-256 encrypt/decrypt helpers
  • Short IDs — thread-safe random ID generation

Quick Start

dotnet add package Halifax.Api
using Halifax.Api;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHalifax();

var app = builder.Build();
app.UseHalifax();
app.Run("https://*:5000");

This gives you controller routing, exception handling, Swagger, Scalar UI, CORS, and structured logging. Explore the Peggy's Cove sample project for a full working example.

API Responses

All endpoints return a consistent format using ApiResponse:

// Return data
return ApiResponse.With(user);

// Return empty success
return ApiResponse.Empty;

Response format:

{
  "data": { ... },
  "success": true,
  "error": null
}

On error:

{
  "data": null,
  "success": false,
  "error": {
    "type": "HalifaxNotFoundException",
    "message": "User not found"
  }
}

Pagination

[HttpGet]
public ApiResponse<Paging<UserDto>> GetUsers([FromQuery] PagingQuery query)
{
    var items = db.Users.Skip(query.Skip).Take(query.Take).ToList();
    var total = db.Users.Count();
    return ApiResponse.With(new Paging<UserDto>(items, query.Skip, query.Take, total));
}

PagingQuery binds Skip, Take, OrderBy, and OrderDirection from query string parameters.

Exceptions

Throw typed exceptions anywhere in your code — the middleware handles the HTTP response:

Exception HTTP Status
HalifaxException 400 Bad Request
HalifaxNotFoundException 404 Not Found
HalifaxUnauthorizedException 401 Unauthorized
var user = await db.Users.FindAsync(id);
if (user == null)
    throw new HalifaxNotFoundException("User not found");

For advanced scenarios, override DefaultExceptionHandler or register your own IExceptionHandler.

Configuration

Halifax loads environment variables from .env files automatically. Define a class or record matching your variable names:

AppSettings__ConnectionString=localhost
AppSettings__HttpTimeout=120
record AppSettings(string ConnectionString, int HttpTimeout);

Register during startup:

builder.Services.AddHalifax(h => h.AddSettings<AppSettings>());

Settings are registered as singletons — inject them into controllers and services, or access them directly:

var settings = Env.GetSection<AppSettings>();

Supported types: string, primitives, DateTime, TimeSpan, Guid, and their nullable variants.

JWT Authentication

Enable authentication with one call:

builder.Services.AddHalifax(h => h
    .ConfigureAuthentication("your_jwt_secret_min_16_chars",
        validateAudience: false,
        validateIssuer: false,
        requireExpirationTime: false));

All non-[AllowAnonymous] endpoints now require Authorization: Bearer {token}.

Creating Tokens

var claims = new List<Claim>
{
    new("sub", user.Id.ToString()),
    new("email", user.Email),
    new("role", user.Role)
};

var token = Jwt.Create("your_jwt_secret", claims, DateTime.UtcNow.AddDays(30));

Reading Tokens

var principal = Jwt.Read("your_jwt_secret", token);

Claims-Based Authorization

Create custom authorization filters by extending ClaimsAuthorizeFilterAttribute:

class AdminOnly : ClaimsAuthorizeFilterAttribute
{
    protected override bool IsAuthorized(ActionExecutingContext context, List<Claim> claims)
    {
        claims.ClaimExpected("role", "admin");
        return true;
    }
}

[HttpGet("admin")]
[AdminOnly]
public ApiResponse GetAdminData() => ApiResponse.With("secret");

Available claim extensions: ClaimExpected, ClaimNotNullOrWhiteSpace, ClaimIsEmail, ClaimIsInt, ClaimIsDouble, ClaimIsEnum<T>, ClaimIsGuid, ClaimIsBoolean.

Validation

Guard provides fluent validation that throws HalifaxException (400) on failure:

Guard.NotNullOrWhiteSpace(request.Name, nameof(request.Name));
Guard.Email(request.Email);
Guard.Length(request.Password, nameof(request.Password), lower: 8, upper: 64);
Guard.Range(request.Age, nameof(request.Age), from: 18, to: 120);
Guard.Url(request.Website, nameof(request.Website));
Guard.Ensure(request.AcceptedTerms, "Terms must be accepted");
Guard.NotNull(request.Address, nameof(request.Address));
Guard.NotEmptyList(request.Tags, nameof(request.Tags));
Guard.Color(request.Theme, nameof(request.Theme));

HTTP Client

Create typed HTTP clients for service-to-service communication by extending HalifaxHttpClient:

public class PaymentClient(HttpClient http) : HalifaxHttpClient(http)
{
    public async Task<PaymentDto> GetAsync(string id)
    {
        var msg = CreateMessage(HttpMethod.Get, $"/api/payments/{id}");
        return await SendAsync<PaymentDto>(msg);
    }

    public async Task<HttpStatusCode> CreateAsync(CreatePaymentRequest request)
    {
        var msg = CreateMessage(HttpMethod.Post, "/api/payments", request);
        return await SendAsync(msg);
    }
}

Register with optional defaults:

services.AddHalifaxHttpClient<PaymentClient>(
    defaultBaseUrl: "https://payments.api.com",
    defaultBearerToken: token);

Error responses (400, 401, 404) from downstream services are automatically mapped to the corresponding Halifax exceptions.

Excel & CSV

dotnet add package Halifax.Excel
var converter = new ExcelConverter<Person>();
converter.AddMapping("Full Name", p => p.Name);
converter.AddMapping("Age", p => p.Age);

// Write
using var stream = new MemoryStream();
await converter.WriteExcelAsync(stream, people, "Sheet1");
await converter.WriteCsvAsync(stream, people);

// Read (auto-detects format from content type)
var records = await converter.ReadAsync(fileStream, contentType);

Utilities

Cryptography

AES-256 encryption:

var encrypted = Crypto.Encrypt("secret", "sensitive data");
var decrypted = Crypto.Decrypt("secret", encrypted);
Crypto.TryDecrypt("secret", encrypted, out var result);

Short IDs

Thread-safe random ID generation:

var id = ShortId.Create();              // e.g. "kX9mBnQ"
var id = ShortId.Create(length: 12);    // longer ID
var id = ShortId.Create(useNumbers: false); // letters only

JSON

Pre-configured serialization (camelCase, case-insensitive, enums as strings, UTC dates):

var json = Json.Serialize(obj);
var obj = Json.Deserialize<MyType>(json);

Logging

Global structured logging via Serilog:

L.Info("User created", userId);
L.Warning("Timeout exceeded");
L.Error(exception, "Failed to process");

Full Configuration Example

builder.Services.AddHalifax(h => h
    .SetName("My Service")
    .AddSettings<AppSettings>()
    .AddSettings<DatabaseSettings>()
    .ConfigureAuthentication(jwtSecret, false, false, false)
    .ConfigureCors(cors => cors
        .AllowAnyHeader()
        .AllowAnyMethod()
        .WithOrigins("https://myapp.com"))
    .ConfigureOpenApi(swagger => { /* customize Swashbuckle */ })
    .ConfigureJson(opts => { /* customize System.Text.Json */ }));

Package Overview

Package Purpose Dependencies
Halifax.Domain Response models, exceptions, pagination None
Halifax.Core JWT, config, validation, crypto, logging, JSON Halifax.Domain, Serilog, System.IdentityModel.Tokens.Jwt
Halifax.Api ASP.NET Core integration, middleware, Swagger Halifax.Core, Swashbuckle, Scalar, JwtBearer
Halifax.Http Typed HttpClient base class Halifax.Core
Halifax.Excel Excel/CSV import and export CsvHelper, ExcelMapper, NPOI

All packages target .NET 10.

MIT License

Copyright (c) 2020 Andrei M

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

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
5.1.1 92 3/2/2026
5.1.0 82 3/2/2026
5.0.1 204 1/28/2026
5.0.0 436 11/14/2025
4.0.4 233 10/4/2025
4.0.3 366 9/3/2025
4.0.2 406 6/25/2025
4.0.1 496 4/6/2025
4.0.0 500 11/19/2024
3.1.4 311 9/10/2024
3.1.3 503 8/7/2024
3.1.2 400 5/10/2024
3.1.1 348 3/11/2024
3.1.0 315 2/11/2024
3.0.1 389 1/24/2024
3.0.0 438 11/17/2023
2.0.8 248 10/30/2023
2.0.7 382 9/14/2023
2.0.6 331 8/16/2023
2.0.5 359 7/9/2023
Loading failed

v5.1.0 - Correlation ID handler, resilience/retry policies, nullable reference types
v5.0.x - .NET 10 support
v4.0.x - .NET 9 support
v3.1.x - Minor improvements to the APIs
v3.0.x - .NET 8 support
v2.0.x - .NET 7 support
v1.0.x - Initial release