CoreSystem.Http.ProblemDetails 1.1.0

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

⚠️ CoreSystem.Http.ProblemDetails

Consistent RFC 9457 Problem Details for ASP.NET Core APIs.

CoreSystem.Http.ProblemDetails provides reusable exception-to-HTTP error handling for ASP.NET Core APIs on .NET 8, .NET 9 and .NET 10. It owns the HTTP mechanism while each application keeps its domain exceptions, business error codes, and mapping rules.

NuGet Downloads License .NET


✨ Features

  • ✅ RFC 9457 application/problem+json responses
  • ✅ Application-owned exception mapping through IExceptionProblemMapper
  • ✅ Standard errorCode and traceId extensions
  • ✅ W3C Activity.Current.TraceId with HttpContext.TraceIdentifier fallback
  • ✅ Application-specific extensions through a callback
  • ✅ Exception type and message exposed only in Development
  • ✅ No dependency on domain, application, or idempotency packages

📦 Installation

dotnet add package CoreSystem.Http.ProblemDetails

🚀 Quick Start

Implement the mapper in the API or Infrastructure layer. Domain and Application projects do not need to reference this package.

using Core.Http.ProblemDetails;
using Core.Http.ProblemDetails.DependencyInjection;
using Microsoft.AspNetCore.Http;

public sealed class ApiExceptionProblemMapper : IExceptionProblemMapper
{
    public ProblemDescriptor Map(Exception exception) => exception switch
    {
        OrderNotFoundException => new(
            StatusCodes.Status404NotFound,
            "ORDER_NOT_FOUND",
            "Order not found",
            "The requested order does not exist",
            "urn:example:error:order-not-found"),
        _ => new(
            StatusCodes.Status500InternalServerError,
            "INTERNAL_ERROR",
            "Unexpected error",
            "An unexpected error occurred")
    };
}

Register Problem Details and the mapper-backed exception handler:

builder.Services.AddCoreProblemDetails();
builder.Services.AddCoreExceptionHandler<ApiExceptionProblemMapper>();

var app = builder.Build();
app.UseExceptionHandler();

AddCoreExceptionHandler<TMapper>() registers the concrete mapper as scoped when it has not already been registered. Register any dependencies required by the mapper in the usual way. The exception handler creates a scope for each handled exception, so scoped mapper dependencies (such as a DbContext) are resolved and disposed correctly.


🔌 Application Extensions

Applications can add fields without introducing domain dependencies into this package. For example, an API that uses CoreSystem.Idempotency can expose the key related to a fingerprint mismatch:

using Core.Idempotency.Exceptions;

builder.Services.AddCoreProblemDetails(options =>
{
    options.CustomizeProblemDetails = (problem, context, exception) =>
    {
        if (exception is IdempotencyFingerprintMismatchException)
        {
            problem.Extensions["idempotencyKey"] =
                context.Request.Headers["Idempotency-Key"].ToString();
        }
    };
});

📄 Response Contract

For an exception mapped to a conflict, the handler produces a response similar to the following:

{
  "type": "urn:example:error:order-already-exists",
  "title": "Order already exists",
  "status": 409,
  "detail": "An order with this identifier already exists",
  "instance": "/orders/42",
  "errorCode": "ORDER_ALREADY_EXISTS",
  "traceId": "4bf92f3577b34da6a3ce929d0e0e4736"
}

The handler provides status, title, detail, type, instance, errorCode, and traceId. If the mapper does not specify a type, the handler uses about:blank.

In Development, exceptionType and exceptionMessage are added. They are omitted in every other environment.


🏗 Architecture

Domain / Application
        │
        ▼
Application Exception Mapper
        │
        ▼
IExceptionProblemMapper
        │
        ▼
CoreExceptionHandler
        │
        ▼
RFC 9457 Problem Details Response

The application owns the vocabulary of errors. CoreSystem owns only reusable HTTP infrastructure.


📖 Public API

Type Description
ProblemDescriptor Domain-agnostic description of an HTTP problem.
IExceptionProblemMapper Maps an exception to a ProblemDescriptor.
AddCoreProblemDetails() Registers RFC 9457 serialization and customization.
AddCoreExceptionHandler<TMapper>() Registers the mapper-backed exception handler.
CoreProblemDetailsOptions Provides the CustomizeProblemDetails callback.

📚 Documentation

The full documentation includes:

  • Getting Started
  • Exception Mapping
  • Application Extensions
  • Response Contract
  • Development Diagnostics
  • Best Practices

🤝 Contributing

Issues, discussions and pull requests are welcome.


📄 License

Released under the MIT License.

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.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

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
1.1.0 105 10/24/2026
1.0.2 102 10/7/2026
1.0.1 141 9/21/2026

Initial release with RFC 9457 Problem Details, exception mapping, trace identifiers, and extension callbacks.
     1.1.0: Targets net8.0, net9.0 and net10.0 (previously net8.0 only). No public API or behavior change; the net9.0 and net10.0 assets are new, and the net8.0 assembly is unchanged. The nuspec no longer declares Microsoft.Extensions.DependencyInjection.Abstractions and Microsoft.Extensions.Options as package dependencies: both assemblies ship in the Microsoft.AspNetCore.App framework reference the package already carries, so consumers are unaffected.