Pandatech.ResponseCrafter 7.0.0

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

Pandatech.ResponseCrafter

Exception-based error handling for ASP.NET Core 8+ with RFC 9457-compliant ProblemDetails, structured logging, and SignalR support.

Note: If you prefer the Result pattern over exception-based error handling, consider **ResultCrafter ** by Haik Asatryan. ResultCrafter provides a more functional approach with explicit error handling through Result types. ResponseCrafter takes a different path—using typed exceptions with automatic ProblemDetails mapping—suitable for teams that prefer traditional exception flows.

Installation

dotnet add package Pandatech.ResponseCrafter

Setup

using ResponseCrafter.Enums;
using ResponseCrafter.Extensions;

builder.AddResponseCrafter(NamingConvention.ToSnakeCase);

// Optional: SignalR support
builder.Services.AddSignalR(o => o.AddFilter<SignalRExceptionFilter>());

var app = builder.Build();

app.UseResponseCrafter();

Quick Start

Throw Typed Exceptions

using ResponseCrafter.HttpExceptions;

app.MapPost("/users", (CreateUserRequest req) =>
{
    // Validation
    BadRequestException.ThrowIfNullOrWhiteSpace(req.Email, "email_required");
    
    // Not found
    var user = db.Users.Find(req.Id);
    NotFoundException.ThrowIfNull(user, "user_not_found");
    
    // Conflict
    if (db.Users.Any(u => u.Email == req.Email))
        throw new ConflictException("email_already_exists");
    
    // With field errors
    throw new BadRequestException("invalid_payload", new Dictionary<string, string>
    {
        ["email"] = "invalid_email_format",
        ["age"] = "must_be_18_or_older"
    });
});

Response Format

All errors return RFC 9457 ProblemDetails:

{
    "requestId": "0HN8K2MJ7F4QP:00000001",
    "traceId": "00-abc123...",
    "instance": "/api/users",
    "statusCode": 400,
    "type": "BadRequestException",
    "message": "invalid_payload",
    "errors": {
        "email": "invalid_email_format",
        "age": "must_be_18_or_older"
    }
}

Available Exceptions

Exception Status Static Helpers
BadRequestException 400 ✅ ThrowIf*, ThrowIfNull*, etc.
UnauthorizedException 401
PaymentRequiredException 402
ForbiddenException 403
NotFoundException 404
ConflictException 409
TooManyRequestsException 429
ForceToChangePasswordException 469
InternalServerErrorException 500
ServiceUnavailableException 503
GatewayTimeoutException 504

Static Helper Methods

All exceptions with static helpers provide:

// Null checks
NotFoundException.ThrowIfNull(user);
NotFoundException.ThrowIfNull(user, "custom_message");

// String checks
BadRequestException.ThrowIfNullOrWhiteSpace(input, "input_required");

// Collection checks
NotFoundException.ThrowIfNullOrEmpty(list, "no_results_found");

// Conditional
ForbiddenException.ThrowIf(condition, "access_denied");

// Numeric checks
BadRequestException.ThrowIfNullOrNegative(amount, "invalid_amount");

Naming Conventions

ResponseCrafter automatically converts error messages and field names to your preferred case:

builder.AddResponseCrafter(NamingConvention.ToSnakeCase);

Available conventions:

  • Default - No transformation
  • ToSnakeCase - user_not_found
  • ToCamelCase - userNotFound
  • ToPascalCase - UserNotFound
  • ToKebabCase - user-not-found
  • ToTitleCase - User Not Found
  • ToHumanCase - User not found
  • ToUpperSnakeCase - USER_NOT_FOUND

SignalR Support

Handle exceptions in SignalR hubs with automatic error broadcasting:

using ResponseCrafter.ExceptionHandlers.SignalR;

// Hub method
public class ChatHub : Hub<IChatClient>
{
    public Task SendMessage(Message request)
    {
        BadRequestException.ThrowIfNullOrWhiteSpace(request.Content, "message_empty");
        
        // Process message...
    }
}

// Request must implement IHubArgument
public class Message : IHubArgument
{
    public required string Content { get; set; }
    public required string InvocationId { get; set; }
}

Client receives error via ReceiveError event:

{
    "traceId": "00-abc123...",
    "invocationId": "unique-call-id",
    "instance": "SendMessage",
    "statusCode": 400,
    "message": "message_empty",
    "errors": null
}

Automatic Exception Mapping

ResponseCrafter automatically handles:

  • DbUpdateConcurrencyException → 409 Conflict
  • FluentImporter exceptions → 400 Bad Request
  • Gridify exceptions → 400 Bad Request
  • BadHttpRequestException (malformed JSON) → 400 with parse details
  • Unhandled exceptions → 500 Internal Server Error

Error Visibility

Control error detail exposure via configuration:

{
    "ResponseCrafterVisibility": "Public"
}
  • Public (default): 5xx errors show generic message, 4xx show actual errors
  • Private: All errors show full details (dev/staging only)

OpenAPI Integration

app.MapPost("/users", (CreateUserRequest req) =>
{
    // ... handler logic
})
.ProducesBadRequest()
.ProducesConflict()
.ProducesNotFound();

Available extension methods:

  • ProducesBadRequest() - 400
  • ProducesUnauthorized() - 401
  • ProducesForbidden() - 403
  • ProducesNotFound() - 404
  • ProducesConflict() - 409
  • ProducesTooManyRequests() - 429
  • ProducesServiceUnavailable() - 503
  • ProducesPaymentRequired() - 402
  • ProducesErrorResponse(statusCode) - Custom status
  • ProducesErrorResponse(params int[]) - Multiple statuses

Advanced Usage

Custom Error Dictionaries

var errors = new Dictionary<string, string>
{
    ["field1"] = "error_message_1",
    ["field2"] = "error_message_2"
};

throw new BadRequestException("validation_failed", errors);
// or
throw new BadRequestException(errors); // Uses default message

Conditional Throwing

BadRequestException.ThrowIf(age < 18, "must_be_adult");
ForbiddenException.ThrowIf(!user.IsAdmin, "admin_only");

Comparison with ResultCrafter

Feature ResponseCrafter ResultCrafter
Approach Exception-based Result-based (functional)
Control flow try/catch Explicit Result<T>
Performance Exception overhead No exceptions
API clarity Implicit errors Explicit in signatures
Best for Traditional .NET teams Teams preferring functional style

Use ResponseCrafter if:

  • Your team is comfortable with exceptions
  • You have existing exception-based code
  • You prefer implicit error handling

Use ResultCrafter if:

  • You want explicit error handling in method signatures
  • You prefer functional programming patterns
  • Performance is critical (no exception overhead)

Configuration Reference

appsettings.json:

{
    "ResponseCrafterVisibility": "Public"
}

Program.cs:

builder.AddResponseCrafter(NamingConvention.ToSnakeCase);
app.UseResponseCrafter();

License

MIT

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 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 (1)

Showing the top 1 NuGet packages that depend on Pandatech.ResponseCrafter:

Package Downloads
Pandatech.SharedKernel

Opinionated ASP.NET Core 10 infrastructure kernel: OpenAPI (Swagger + Scalar), Serilog, MediatR, FluentValidation, CORS, SignalR, OpenTelemetry, health checks, maintenance mode, resilience pipelines, and shared utilities.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
7.0.0 34 2/28/2026
6.0.2 53 2/26/2026
6.0.1 126 1/26/2026
6.0.0 106 12/28/2025
5.3.1 179 12/23/2025
5.3.0 257 10/30/2025
5.2.2 257 9/8/2025
5.2.1 202 9/8/2025
5.2.0 193 8/15/2025
5.1.12 284 8/7/2025
5.1.11 181 7/30/2025
5.1.10 315 6/1/2025
5.1.9 294 4/9/2025
5.1.8 265 2/18/2025
5.1.7 217 2/17/2025
5.1.6 215 2/5/2025
5.1.5 224 1/10/2025
5.1.4 180 1/9/2025
5.1.3 224 12/18/2024
5.1.2 220 12/17/2024
Loading failed

Multi-target net8.0/9.0/10.0, source-generated logging, path-only instance URIs, updated dependencies, fixed extension method syntax