ArchSoft.Http.Exceptions 1.0.2

dotnet add package ArchSoft.Http.Exceptions --version 1.0.2
                    
NuGet\Install-Package ArchSoft.Http.Exceptions -Version 1.0.2
                    
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="ArchSoft.Http.Exceptions" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ArchSoft.Http.Exceptions" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="ArchSoft.Http.Exceptions" />
                    
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 ArchSoft.Http.Exceptions --version 1.0.2
                    
#r "nuget: ArchSoft.Http.Exceptions, 1.0.2"
                    
#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 ArchSoft.Http.Exceptions@1.0.2
                    
#: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=ArchSoft.Http.Exceptions&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=ArchSoft.Http.Exceptions&version=1.0.2
                    
Install as a Cake Tool

ArchSoft.Http.Exceptions

NuGet License .NET

A .NET library that provides strongly-typed HTTP exceptions for building robust REST APIs. Includes factory classes for bidirectional conversion between HTTP status codes and exceptions.

πŸ“„ DocumentaΓ§Γ£o em PortuguΓͺs (Brazilian Portuguese)

πŸš€ Installation

dotnet add package ArchSoft.Http.Exceptions

✨ Features

  • 🎯 20+ Typed Exceptions - Specific exception classes for each HTTP status code
  • πŸ”„ HttpExceptionFactory - Convert HttpStatusCode to typed exceptions
  • πŸ”™ HttpStatusCodeFactory - Convert exceptions to HttpStatusCode with automatic mapping
  • 🧩 Native Exception Support - Automatic mapping of ArgumentException, InvalidOperationException, etc.
  • βœ… Fully Tested - Complete unit test suite with xUnit
  • ⚑ Zero Dependencies - Lightweight library with no external dependencies

πŸ“– Use Cases

  • REST APIs - Throw typed exceptions from controllers and services
  • Exception Middleware - Centralized error handling in ASP.NET Core
  • API Clients - Convert HTTP error responses to typed exceptions
  • Microservices - Standardized error handling across services
  • Domain Services - Business rule validation with appropriate HTTP status

πŸ“‹ Available Exceptions

Exception Code When to Use
BadRequestException 400 Invalid request data or malformed syntax
UnauthorizedException 401 Missing or invalid authentication
ForbiddenException 403 Authenticated but not authorized
NotFoundException 404 Resource does not exist
MethodNotAllowedException 405 HTTP method is not supported for the resource
NotAcceptableException 406 Resource cannot generate content acceptable according to Accept headers
RequestTimeoutException 408 Request took too long to process
ConflictException 409 Resource state conflict
GoneException 410 Resource permanently removed
PreconditionFailedException 412 One or more conditions in the request headers failed
PayloadTooLargeException 413 Request entity is larger than limits defined by server
UnsupportedMediaTypeException 415 Media format of the requested data is not supported
UnprocessableEntityException 422 Valid syntax but semantic errors
TooManyRequestsException 429 User has sent too many requests in a given amount of time
InternalServerErrorException 500 Unexpected server error
NotImplementedException 501 Feature not yet implemented
BadGatewayException 502 Invalid response from upstream
ServiceUnavailableException 503 Service temporarily unavailable
GatewayTimeoutException 504 Upstream server timeout
InsufficientStorageException 507 Server cannot store representation
LoopDetectedException 508 Infinite loop detected

πŸ’» Basic Usage

Throwing Exceptions in Services

using ArchSoft.Http.Exceptions;

public class UserService
{
    private readonly IUserRepository _repository;

    public UserService(IUserRepository repository)
    {
        _repository = repository;
    }

    public async Task<User> GetByIdAsync(int id)
    {
        var user = await _repository.FindByIdAsync(id);

        if (user == null)
            throw new NotFoundException($"User with ID {id} was not found");

        return user;
    }
}

Validation Errors

public class CreateUserService
{
    public async Task<User> CreateAsync(CreateUserRequest request)
    {
        // Invalid data - 400 Bad Request
        if (string.IsNullOrWhiteSpace(request.Email))
            throw new BadRequestException("Email is required");

        if (!IsValidEmail(request.Email))
            throw new BadRequestException("Email format is invalid");

        // Business conflict - 409 Conflict
        if (await _repository.EmailExistsAsync(request.Email))
            throw new ConflictException($"Email '{request.Email}' is already registered");

        return await _repository.CreateAsync(request);
    }
}

Authentication & Authorization

public class OrderService
{
    public async Task<Order> GetOrderAsync(int orderId, int userId)
    {
        // Not authenticated - 401 Unauthorized
        if (userId == 0)
            throw new UnauthorizedException("Authentication required to access orders");

        var order = await _repository.FindByIdAsync(orderId);

        // Not found - 404 Not Found
        if (order == null)
            throw new NotFoundException($"Order {orderId} was not found");

        // Access denied - 403 Forbidden
        if (order.UserId != userId && !await _userService.IsAdminAsync(userId))
            throw new ForbiddenException("You do not have permission to access this order");

        return order;
    }
}

πŸ”§ Advanced Examples

Soft Delete Pattern

public class DocumentService
{
    public async Task<Document> GetDocumentAsync(int id)
    {
        var document = await _repository.FindByIdAsync(id);

        if (document == null)
            throw new NotFoundException($"Document {id} not found");

        // Document was soft-deleted - 410 Gone
        if (document.IsDeleted)
            throw new GoneException($"Document {id} has been permanently removed");

        return document;
    }
}

Business Rule Validation

public class PaymentService
{
    public async Task ProcessPaymentAsync(PaymentRequest request)
    {
        // Semantically invalid - 422 Unprocessable Entity
        if (request.Amount <= 0)
            throw new UnprocessableEntityException("Payment amount must be greater than zero");

        if (request.Amount > _maxPaymentAmount)
            throw new UnprocessableEntityException($"Amount exceeds maximum limit of {_maxPaymentAmount}");

        // Process payment...
    }
}

External Service Integration

public class ExternalApiService
{
    public async Task<ApiResponse> CallExternalServiceAsync()
    {
        try
        {
            var response = await _httpClient.GetAsync("api/external");

            if (!response.IsSuccessStatusCode)
            {
                var message = await response.Content.ReadAsStringAsync();
                throw HttpExceptionFactory.Create(response.StatusCode, message);
            }

            return await response.Content.ReadFromJsonAsync<ApiResponse>();
        }
        catch (HttpRequestException ex)
        {
            // Upstream service error - 502 Bad Gateway
            throw new BadGatewayException("External service returned an invalid response", ex);
        }
    }
}

Maintenance Mode

public class MaintenanceMiddleware
{
    public async Task InvokeAsync(HttpContext context)
    {
        if (_maintenanceService.IsUnderMaintenance())
        {
            // Service temporarily unavailable - 503 Service Unavailable
            throw new ServiceUnavailableException(
                "Service is under maintenance. Please try again later.");
        }

        await _next(context);
    }
}

πŸ”„ Using Factories

HttpExceptionFactory - Convert StatusCode to Exception

using ArchSoft.Http.Exceptions.Factories;
using System.Net;

public class ApiClient
{
    public async Task<T> GetAsync<T>(string endpoint)
    {
        var response = await _httpClient.GetAsync(endpoint);

        if (!response.IsSuccessStatusCode)
        {
            var error = await response.Content.ReadAsStringAsync();
            throw HttpExceptionFactory.Create(response.StatusCode, error);
        }

        return await response.Content.ReadFromJsonAsync<T>();
    }
}

HttpStatusCodeFactory - Convert Exception to StatusCode

using ArchSoft.Http.Exceptions.Factories;
using System.Net;

public class ExceptionMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            var statusCode = HttpStatusCodeFactory.Create(ex);

            context.Response.StatusCode = (int)statusCode;
            await context.Response.WriteAsJsonAsync(new
            {
                Status = (int)statusCode,
                Error = ex.Message,
                Timestamp = DateTime.UtcNow
            });
        }
    }
}

Native Exception Mapping

// Native .NET exceptions are automatically mapped:
// ArgumentException          β†’ 400 Bad Request
// InvalidOperationException  β†’ 409 Conflict
// TimeoutException           β†’ 408 Request Timeout
// NotImplementedException    β†’ 501 Not Implemented

public async Task<IActionResult> ProcessOrder(int orderId)
{
    try
    {
        await _orderService.ProcessAsync(orderId);
        return Ok();
    }
    catch (ArgumentException ex)
    {
        // HttpStatusCodeFactory returns 400 Bad Request
        var statusCode = HttpStatusCodeFactory.Create(ex);
        return StatusCode((int)statusCode, ex.Message);
    }
}

πŸ“ Complete Exception Handling Example

// Program.cs - ASP.NET Core
var app = builder.Build();

app.UseMiddleware<ExceptionHandlingMiddleware>();

app.MapControllers();
app.Run();

// ExceptionHandlingMiddleware.cs
public class ExceptionHandlingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionHandlingMiddleware> _logger;

    public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        var statusCode = HttpStatusCodeFactory.Create(exception);

        _logger.LogError(exception, "Request failed with status {StatusCode}", statusCode);

        context.Response.StatusCode = (int)statusCode;
        context.Response.ContentType = "application/json";

        var response = new ErrorResponse(
            Status: (int)statusCode,
            Error: exception.Message,
            Path: context.Request.Path
        );

        await context.Response.WriteAsJsonAsync(response);
    }
}

public record ErrorResponse(int Status, string Error, string Path);

⚠️ Important Notes

  • All exceptions inherit from System.Exception with three constructors
  • HttpStatusCodeFactory.Create(null) returns 500 Internal Server Error
  • Unknown exceptions default to 500 Internal Server Error
  • Use HttpExceptionFactory for converting status codes from external APIs

πŸ“‹ Requirements

  • .NET 8.0 or higher

🀝 Contributing

Contributions are welcome! Please open an issue or pull request.

πŸ“„ License

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

🏒 About

Developed by ArchSoft - Software solutions.

Product Compatible and additional computed target framework versions.
.NET 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on ArchSoft.Http.Exceptions:

Package Downloads
ArchSoft.CustomExceptions

Collection of custom exceptions for .NET applications, delegating HTTP handling to ArchSoft.Http.Exceptions.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 164 3/27/2026
1.0.1 116 3/26/2026
1.0.0 264 3/28/2024