Siemens.AspNet.ErrorHandling
7.4.1
Prefix Reserved
See the version list below for details.
dotnet add package Siemens.AspNet.ErrorHandling --version 7.4.1
NuGet\Install-Package Siemens.AspNet.ErrorHandling -Version 7.4.1
<PackageReference Include="Siemens.AspNet.ErrorHandling" Version="7.4.1" />
<PackageVersion Include="Siemens.AspNet.ErrorHandling" Version="7.4.1" />
<PackageReference Include="Siemens.AspNet.ErrorHandling" />
paket add Siemens.AspNet.ErrorHandling --version 7.4.1
#r "nuget: Siemens.AspNet.ErrorHandling, 7.4.1"
#:package Siemens.AspNet.ErrorHandling@7.4.1
#addin nuget:?package=Siemens.AspNet.ErrorHandling&version=7.4.1
#tool nuget:?package=Siemens.AspNet.ErrorHandling&version=7.4.1
Siemens.AspNet.ErrorHandling
The Siemens.AspNet.ErrorHandling package provides middleware and services for handling errors in ASP.NET Core
applications. It includes features for translating error messages based on the "Accepted Languages" header, making it
easier to build multilingual applications with standardized error responses. The package is designed to work seamlessly
with its companion package,
Siemens.AspNet.ErrorHandling.Contracts Link to Documentation,
which defines the core error handling models and base classes like ProblemDetails and ValidationProblemDetails.
By using RFC 7807, we ensure that error responses are consistent, easily interpretable by clients, and capable of conveying rich, structured information about errors. This approach enhances interoperability and helps developers diagnose issues more effectively.
π Installation
You can install the package using NuGet:
.NET CLI
dotnet add package Siemens.AspNet.ErrorHandling
NuGet Package Manager Console
Install-Package Siemens.AspNet.ErrorHandling
π Getting Started
1. Register the Middleware and Services
In your ASP.NET Core application, you need to register the error handling services in the Startup.cs or Program.cs file.
AddErrorHandling adds all services for handling response error and logging (see the example below).
If you want to add only the error logging, please add and use AddErrorLogHandling and UseErrorLogHandling.
If you want to add only the handler itself to handle the error responses, please add AddErrorResponseHandling and
UseErrorResponseHandling.
When using the AddErrorHandling method, it will also add the following service options:
builder.Services.Configure<RouteHandlerOptions>(options =>
{
options.ThrowOnBadRequest = true;
});
π§ Example Scenario:
With ThrowOnBadRequest = false
POST /api/submit
Body: { "age": "not_a_number" }
β 400 Bad Request (no exception thrown)
With ThrowOnBadRequest = true
POST /api/submit
Body: { "age": "not_a_number" }
β Throws exception (Model binding failure)
if you override the default behavior of the RouteHandlerOptions make sure to set the ThrowOnBadRequest=true!
Dotnet 7
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Register the error handler services for logging or response handling
// services.AddErrorResponseHandling();
// services.AddErrorLogHandling();
// Register the error handling services
services.AddErrorHandling();
// Other service registrations...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Add the error response handling
// app.UseErrorResponseHandling();
// Add the error Logging
// app.UseErrorLogHandling();
// Add the error handling middleware to the request pipeline
app.UseErrorHandlingMiddleware();
// Other middleware...
}
}
Dotnet 8 or higher
var builder = WebApplication.CreateBuilder(args);
// Register the error handler services for logging or response handling
// builder.Services.AddErrorResponseHandling();
// builder.Services.AddErrorLogHandling();
// Register the error handling services
builder.Services.AddErrorHandling();
// Other service registrations...
var app = builder.Build();
app.UseRouting();
// Important to use the full potential setup the error handler after app.UseRouting();
app.UseErrorHandling();
// Other middleware...
app.Run();
With Siemens.AspNet.MinimalApi.Sdk
If you use the Siemens.AspNet.MinimalApi.Sdk (coming soon) package everything is already setup. Just use the
ServerlessMinimalWebApi and everything
is ready to go.
using Pulse.FieldingTool.Api;
using Siemens.AspNet.MinimalApi.Sdk;
var webApi = new ServerlessMinimalWebApi();
webApi.RegisterServices = (service,
config) =>
{
// Domain service registrations
service.AddApi(config);
};
webApi.MapEndpoints = endpoints =>
{
// Map api domain endpoints
endpoints.MapApi();
};
webApi.Run(args);
// This is important that you are able to use
// API test via WebApplicationFactory<Program>
// https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-8.0
namespace Pulse.FieldingTool
{
public partial class Program;
}
βοΈ Optional Configuration
π Show Error Details
(Optional) A new feature has been introduced that allows you to control which error response will be processed and which will ne hidden from the user
Configuration
To conifgure this feature, add the following configuration to your appsettings.json or set it as an environment variable:
Example: Single codes
"ErrorHandlerSettings": {
"ShowExceptionDetailsOnErrorCodeRanges": "200;201;202"
}
Example: Ranges (0-499)
"ErrorHandlerSettings": {
"ShowExceptionDetailsOnErrorCodeRanges": "0-400"
}
Example: Single numbers and ranges
"ErrorHandlerSettings": {
"ShowExceptionDetailsOnErrorCodeRanges": "200;210-299;400-499"
}
Default settings: if you are not configure this settings explicitly everything in the range from 0-499 will be handled and shown. All above will be hidden.
Sample: Handled response
{
"type": "ValidationProblemDetails",
"title": "Your patch request contains invalid data",
"status": 422,
"detail": "Your PatchFormsConfigurationRequest for the object id: 6f9e1c3e-8fbc-4d2a-9a3d-3c2e8f0b7d2f was invalid. Please check the error details. You might pass invalid data, or try to patch properties which not exists or not allow to patch",
"errors": {
"formsId": [
"FormsId must be either GUID or long.",
"FormsId must not be one or more whitespace. Only GUID or a long is valid for the ProjectId"
]
}
Sample: Hidden response
{
"type": "ProblemDetails",
"title": "An unexpected error occured, please contact the service",
"status": 422,
"detail": "An unexpected error occured, please contact the service",
"errors": {}
}
Extended Validation problem details:
- Setup AllowedBodyMetaInfo at your endpoint You have to pass the type for your http content type (body). Only needed on http endpoints which have a body like POST, PUT, PATCH.
endpoints.WithMetadata(new AllowedBodyMetaInfo(typeof(CreateFormsConfigurationRequest))); // Your request body type
- Use
ValidationProblemDetailsExtended``instead ofValidationProblemDetails`
endpoints.Produces<ValidationProblemDetailsExtended>(StatusCodes.Status422UnprocessableEntity)
Sample endpoint:
internal static class CreateFormsConfigurationEndpoint
{
internal static void MapCreateFormsConfiguration(this IEndpointRouteBuilder endpoints)
{
endpoints.MapPost("formsConfigurations", HandleAsync)
.Produces<CreateFormsConfigurationResponse>()
.Produces<ProblemDetails>(StatusCodes.Status400BadRequest)
.Produces<ProblemDetails>(StatusCodes.Status401Unauthorized)
.Produces<ProblemDetails>(StatusCodes.Status403Forbidden)
.Produces<ProblemDetails>(StatusCodes.Status404NotFound)
.Produces<ProblemDetails>(StatusCodes.Status409Conflict)
.Produces<ValidationProblemDetailsExtended>(StatusCodes.Status422UnprocessableEntity)
.Produces<ProblemDetails>(StatusCodes.Status500InternalServerError)
.Produces<ProblemDetails>(StatusCodes.Status503ServiceUnavailable)
.Produces<string>(StatusCodes.Status504GatewayTimeout) // AWS handled error -> returns HTML
.WithTags("FormsConfigurations")
.WithName("createFormsConfigurationV1")
.MapToApiVersion(1)
.WithDescriptionFromFile("Description.txt")
.WithSummaryFromFile("Summary.txt")
.WithMetadata(new AllowedBodyMetaInfo(typeof(CreateFormsConfigurationRequest)));
static async Task<CreateFormsConfigurationResponse> HandleAsync(CreateFormsConfigurationRequest createFormsConfigurationRequest,
CreateFormsConfigurationCommand createFormsConfigurationCommand,
CancellationToken cancellationToken = default)
{
var project = await createFormsConfigurationCommand.ExecuteAsync(createFormsConfigurationRequest, cancellationToken).ConfigureAwait(false);
return new CreateFormsConfigurationResponse(project);
}
}
}
New outcome:
{
"type": "ValidationProblemDetailsExtended",
"title": "Your patch request contains invalid data",
"status": 422,
"detail": "Your PatchFormsConfigurationRequest for the object id: 6f9e1c3e-8fbc-4d2a-9a3d-3c2e8f0b7d2f was invalid. Please check the error details. You might pass invalid data, or try to patch properties which not exists or not allow to patch",
"errors": {
"formsId": [
"FormsId must be either GUID or long.",
"FormsId must not be one or more whitespace. Only GUID or a long is valid for the ProjectId"
]
},
"errorDetails": {
"formsId": {
"currentValue": " ",
"errors": [
"FormsId must be either GUID or long.",
"FormsId must not be one or more whitespace. Only GUID or a long is valid for the ProjectId"
],
"samples": [
"a1b2c3d4-e5f6-7890-1234-567890abcdef",
"1"
],
"location": null
}
},
"Id": "6f9e1c3e-8fbc-4d2a-9a3d-3c2e8f0b7d2f",
"RequestType": "PatchFormsConfigurationRequest",
"RequestContent": {
"formsId": " ",
"projectId": "c36b49ba-bf79-4c86-9d41-8c356634316e",
"title": "$UniqueFormsConfigurationName$",
"formsType": "InvitationOnly",
"startDate": "2025-03-15T18:32:18Z",
"endDate": "2025-04-14T18:23:44Z",
"sessionEndsIn": "00:30:00",
"hasUpdate": false,
"languages": [
{
"englishName": "English (United States)",
"nativeName": "English (United States)",
"tag": "en-US",
"tagThreeLetter": "eng",
"parentTag": "en"
}
],
"properties": {
"exampleKey": "ExampleValue"
}
}
}
Invalid Json:
To have even better json error responses if the json payload is invalid we added a new feature to handle this.
Error json:
{
"Id": {%$$},
"DisplayName": "$UniqueEdgeName$",
"SourceCapabilityId": "$SourceCapabilityId$",
"TargetCapabilityId": "$TargetCapabilityId$",
"RelationType": "Simple",
"Position": {
"x": 0,
"y": 1
},
"Size": {
"Width": 2,
"Height": 3
}
}
Orginal Minimal API Response: (Without this error handler)
{
"content": {
"headers": [],
"value": {}
},
"statusCode": "BadRequest",
"headers": [
{
"key": "api-supported-versions",
"value": [
"1"
]
}
],
"trailingHeaders": [],
"isSuccessStatusCode": false
}
With the error handler
{
"type":"ValidationProblemDetailsExtended",
"title":"JsonReaderException was thrown.",
"status":422,
"detail":"Invalid property identifier character: %",
"errorDetails":{
"id":{
"currentValue":"{%$$}",
"errors":[
"Invalid property identifier character: %"
],
"samples":[
"example text"
],
"location":{
"row":"2",
"column":"9"
}
}
},
"errors":{
"id":[
"Invalid property identifier character: % Location line number: \u00272\u0027 line position: \u00279\u0027"
]
}
}
Hint: SampleValues
If you have properties which presents for example an string but can be a Guid or number you can optimize the errors
thrown by System.Text.Json or Newtonsoft.Json easily by adding an attribute over your properties in your request.
This is very useful if you have any crash by your serializers before you enter your endpoint code
public sealed record UpdateFormsConfigurationRequest
{
[SampleValue("a1b2c3d4-e5f6-7890-1234-567890abcdef", "1")]
public required string FormsId { get; init; } // SDC --> FormsId GUID // Pulse --> SurveyInstanceId long
[SampleValue("a1b2c3d4-e5f6-7890-1234-567890abcdef", "1")]
public required string ProjectId { get; init; } // SDC --> GUID // Pulse -->
}
Special Case: ValidationProblemDetailsException
When the thrown exception is a ValidationProblemDetails exception, this configuration not only hides the details but also filters the validation errors themselves. This ensures that no validation error messages are exposed in the response.
With this configuration, whenever an error with the specified code (e.g., 400, 422, 500) or within the specified range ( 500-590) is thrown, detailed error messages will be hidden from the response.
π Translations
(Optional)
The Siemens.AspNet.ErrorHandling package offers robust support for translating error messages based on the client's "
Accepted Languages" header. This is achieved through a pattern-based approach to localization keys, allowing for
consistent and easily maintainable translations across your application.
Language Handling
The Siemens.AspNet.ErrorHandling package automatically selects the appropriate language for error messages based on
the client's "Accepted-Languages" HTTP header. Hereβs how the language handling works:
- <b>Language Selection:</b> The package reads the "Accepted-Languages" header from the client's request to determine the preferred language. This header can contain one or more language codes, and the package will attempt to match these codes with your available translation files.
- <b>Default Language:</b> If the client's preferred language is not available or not specified, the package defaults to English (en).
- <b>Fallback Mechanism:</b> The package leverages the CultureInfo class to handle language fallbacks. If a specific language variant (e.g., de-DE for German in Germany) is not available, the package will automatically fall back to the parent language (e.g., de for general German). This ensures that even if a specific translation is missing, the client still receives an error message in a related language.
For example, if the client requests de-DE (German for Germany) but only de.json is available, the package will use the translations from de.json. This fallback mechanism ensures that users receive the most appropriate localized content available.
Translation Files
To manage translations effectively, the Siemens.AspNet.ErrorHandling package uses JSON files for storing localized
error messages. Follow these guidelines to set up your translation files:
- <b>File Format</b>: The translation files are in JSON format, where each file corresponds to a specific language.
- <b>Folder Organization</b>: Place your translation files in a dedicated folder like "Translations" or " ErrorTranslations". This helps you easily locate and manage your translation files.
- <b>File Naming Convention</b>: Name your translation files based on the language code, such as de.json for German or en.json for English. This ensures clarity and consistency in your localization resources.
By organizing your translation files in this manner, you can maintain a clean and efficient structure that makes it easy to manage and update your localized content.
Translation Key Pattern
The translation keys for error messages follow a specific pattern, making it straightforward to manage translations for different exception types and scenarios. The pattern is as follows:
- Title Translation Key: {Caller}.{ExceptionName}.Title.{TheExceptionTitle}
- Details Translation Key: {Caller}.{ExceptionName}.Details.{TheExceptionTitle}
- Errors Translation Key: {Caller}.{ExceptionName}.Errors.{TheExceptionTitle}.{ErrorKey}
Variables:
- {Caller} - refers to the class or method that raised the exception.
- {ExceptionName} - is the name of the exception class.
- {TheExceptionTitle} - is a key representing the specific error context.
- {ErrorKey} - represents the specific validation or error message key.
Example
Consider a scenario where you have a ValidationDetailsException in a class or method named MyAwesomeClass. The translation keys might look like this:
{
"MyAwesomeClass.ValidationDetailsException.Title.AUTH_TITLE_KEY": "This is my translated title",
"MyAwesomeClass.ValidationDetailsException.Details.AUTH_TITLE_KEY": "This is my translated details",
"MyAwesomeClass.ValidationDetailsException.Errors.AUTH_TITLE_KEY.Name.Name is required.": "This is my translated errors for name 1",
"MyAwesomeClass.ValidationDetailsException.Errors.AUTH_TITLE_KEY.Name.Name must be at least 3 characters long.": "This is my translated errors for name 2",
"MyAwesomeClass.ValidationDetailsException.Errors.AUTH_TITLE_KEY.Email.Email is not in a valid format.": "This is my translated errors for email"
}
This example shows how to throw an error in your c# code.
var errors = new Dictionary<string, string[]>
{
{ "Name", new[] { "Name is required.", "Name must be at least 3 characters long." } },
{ "Email", new[] { "Email is not in a valid format." } }
};
throw new ValidationDetailsException("AUTH_TITLE_KEY", "AUTH_DETAILS_KEY", errors);
π― Error Enrichment
The error enrichment system allows you to add custom metadata to error responses and logs before they are sent to clients or written to your logging infrastructure. This is useful for adding correlation IDs, environment information, user context, or any other application-specific data.
Quick Start
- Implement an enricher:
public class MyCustomResponseEnricher : IErrorResponseEnricher
{
public Task<ProblemDetails> EnrichAsync(ProblemDetails problemDetails,
HttpCallInfos httpCallInfos,
Exception exception)
{
// Add custom metadata
problemDetails.Extensions["timestamp"] = DateTime.UtcNow.ToString("o");
problemDetails.Extensions["environment"] = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
problemDetails.Extensions["traceId"] = httpCallInfos.TraceId;
return Task.FromResult(problemDetails);
}
}
- Register in your DI container:
services.AddSingleton<IErrorResponseEnricher, MyCustomResponseEnricher>();
That's it! The enricher will automatically be discovered and applied to all error responses.
Enrichment Points
The system provides two enrichment points:
1. Response Enrichment (IErrorResponseEnricher)
Enriches ProblemDetails objects before they are written to the HTTP response:
public class CorrelationIdEnricher : IErrorResponseEnricher
{
public Task<ProblemDetails> EnrichAsync(ProblemDetails problemDetails,
HttpCallInfos httpCallInfos,
Exception exception)
{
problemDetails.Extensions["correlationId"] = Guid.NewGuid().ToString();
problemDetails.Extensions["requestPath"] = httpCallInfos.RequestPath;
return Task.FromResult(problemDetails);
}
}
2. Log Enrichment (IErrorLogEnricher)
Enriches ErrorLogInfo objects before they are serialized and logged:
public class UserContextLogEnricher : IErrorLogEnricher
{
public Task<ErrorLogInfo> EnrichAsync(ErrorLogInfo errorLogInfo,
HttpCallInfos httpCallInfos,
Exception exception)
{
return Task.FromResult(errorLogInfo with
{
Extensions = errorLogInfo.Extensions
.Add("userId", httpCallInfos.HttpContext.User?.Identity?.Name ?? "anonymous")
.Add("ipAddress", httpCallInfos.HttpContext.Connection.RemoteIpAddress?.ToString())
});
}
}
Async Operations
Enrichers support async operations, enabling database lookups, external API calls, or other I/O operations:
public class AsyncMetadataEnricher(IMetadataService metadataService) : IErrorResponseEnricher
{
public async Task<ProblemDetails> EnrichAsync(ProblemDetails problemDetails,
HttpCallInfos httpCallInfos,
Exception exception)
{
// Perform async operation
var metadata = await metadataService.GetErrorMetadataAsync(exception.GetType());
problemDetails.Extensions["errorCategory"] = metadata.Category;
problemDetails.Extensions["recommendedAction"] = metadata.RecommendedAction;
return problemDetails;
}
}
Execution Order
Multiple enrichers are executed in the order they are registered:
services.AddSingleton<IErrorResponseEnricher, FirstEnricher>(); // Runs first
services.AddSingleton<IErrorResponseEnricher, SecondEnricher>(); // Runs second
services.AddSingleton<IErrorResponseEnricher, ThirdEnricher>(); // Runs third
Error Handling
Enrichment failures are automatically caught and logged by the default enrichment strategy. This ensures that enrichment errors don't break the main error handling flow:
// Even if this enricher throws an exception, the error response will still be sent
public class RiskyEnricher : IErrorResponseEnricher
{
public async Task<ProblemDetails> EnrichAsync(ProblemDetails problemDetails,
HttpCallInfos httpCallInfos,
Exception exception)
{
// If this throws, it won't break the error response
var data = await ExternalService.GetDataAsync();
problemDetails.Extensions["externalData"] = data;
return problemDetails;
}
}
Custom Enrichment Strategy
If you need more control over how enrichers are executed (e.g., priority-based, conditional, or first-match-only), you can implement a custom strategy:
public class PriorityBasedEnrichmentStrategy : IErrorResponseEnrichmentStrategy
{
private readonly IEnumerable<IErrorResponseEnricher> _enrichers;
public PriorityBasedEnrichmentStrategy(IEnumerable<IErrorResponseEnricher> enrichers)
{
_enrichers = enrichers.OrderBy(e => GetPriority(e));
}
public async Task<ProblemDetails> EnrichAsync(ProblemDetails problemDetails,
HttpCallInfos httpCallInfos,
Exception exception)
{
var enriched = problemDetails;
foreach (var enricher in _enrichers)
{
enriched = await enricher.EnrichAsync(enriched, httpCallInfos, exception);
}
return enriched;
}
private int GetPriority(IErrorResponseEnricher enricher) { /* ... */ }
}
// Register your custom strategy
services.AddSingleton<IErrorResponseEnrichmentStrategy, PriorityBasedEnrichmentStrategy>();
Common Use Cases
- Distributed Tracing: Add correlation IDs, trace IDs, span IDs
- Multi-Tenancy: Include tenant/organization identifiers
- Environment Context: Add environment info (dev/staging/production)
- User Context: Include user IDs, roles, permissions
- Performance Metrics: Add request timing, resource usage
- Feature Flags: Include active feature flags for debugging
- Security Audit: Add security-relevant context (auth method, IP address)
- Monitoring Integration: Add metadata for APM tools (DataDog, New Relic, etc.)
Integration Points
The enrichment system is automatically integrated into the error handling pipeline:
- Response Enrichment: Applied in
ErrorHandlingStrategybeforeWriteResponseAsync() - Log Enrichment: Applied in
SpecificErrorLogHandlerbefore serialization and logging
No additional configuration or middleware setup is required beyond registering your enrichers in the DI container.
For more details on the interfaces and contract definitions, see the Siemens.AspNet.ErrorHandling.Contracts Documentation.
π οΈ Custom Handlers & Logging
π§ Custom Error Handler
If you have the need to handle specific exceptions in a better way as the current handler supports you can implement your own specific error handler quite easy:
- Implement your specific error handler: You only have to provide a ProblemDetails object back. You have 3 levels of ProblemDetails:
- ProblemDetails
- ValidationProblemDetails
- ValidationProblemDetailsExtended (best possible output for validations)
internal static class AddExceptionILikeToHandleHandlerExtension
{
public static void AddExceptionILikeToHandleHandler(this IServiceCollection services)
{
services.AddSingletonIfNotExists<ISpecificErrorHandler, ExceptionILikeToHandleHandler>();
}
}
internal sealed class ExceptionILikeToHandleHandler() : SpecificErrorHandler<ExceptionILikeToHandle>
{
protected override Task<ProblemDetails> HandleExceptionAsync(HttpContext context,
ExceptionILikeToHandle exception)
{
// Add here your custom logic, code to extract infos specific on your exception you like to handle in a specific way
var reducedProblemDetails = new ProblemDetails
{
Title = exception.Message,
Status = problemDetails.Status ?? StatusCodes.Status500InternalServerError,
Type = nameof(ProblemDetails),
Detail = exception.Message,
};
return Task.FromResult(exception.ProblemDetails);
}
}
- Register your new service
using Pulse.FieldingTool.Api;
using Siemens.AspNet.MinimalApi.Sdk;
var webApi = new ServerlessMinimalWebApi();
webApi.RegisterServices = (service,
config) =>
{
// Domain service registrations
service.AddApi(config);
// Custom error handling
service.AddExceptionILikeToHandleHandler()
};
webApi.MapEndpoints = endpoints =>
{
// Map api domain endpoints
endpoints.MapApi();
};
webApi.Run(args);
π Custom Error Logging
If you have the need to handle specific exceptions in a better way as the current handler supports you can implement your own specific error log handler quite easy:
- Implement your specific error log handler: You only have to provide a ErrorLogInfo object back.
internal static class AddValidationProblemDetailsExtendedExceptionLogHandlerExtensions
{
public static void AddValidationProblemDetailsExtendedExceptionLogHandler(this IServiceCollection services)
{
services.AddExceptionLocalizerService();
services.AddTranslationService();
services.AddExceptionHelper();
services.AddSingletonIfNotExists<ISpecificErrorLogHandler, ValidationProblemDetailsExtendedExceptionLogHandler>();
}
}
internal sealed class ValidationProblemDetailsExtendedExceptionLogHandler(ILogger<DefaultExceptionLogHandler> logger,
JsonSerializerOptions jsonSerializerOptions,
ExceptionHelper exceptionHelper) : SpecificErrorLogHandler<ValidationProblemDetailsExtendedException>(logger, jsonSerializerOptions, exceptionHelper)
{
protected override Task<ErrorLogInfo> GetErrorLogFromAsync(HttpContext httpContext,
ValidationProblemDetailsExtendedException exception)
{
// Here you can implement what ever you like to log or customize it.
var errorLogInfo = new ErrorLogInfo
{
StatusCode = exception.ValidationProblemDetailsExtended.Status ?? 500,
Title = exception.ValidationProblemDetailsExtended.Title ?? "No title provided",
Message = exception.ValidationProblemDetailsExtended.Detail ?? "No details provided",
StackTrace = exception.StackTrace?.Split(Environment.NewLine).ToImmutableList() ?? ImmutableList<string>.Empty,
RequestInfos = httpContext.Request.GetQueryRequestInfo(exception.ValidationProblemDetailsExtended.Extensions).ToImmutableDictionary(k => k.key, v => v.value),
ErrorDetails = exception.ValidationProblemDetailsExtended.ErrorDetails.ToImmutableDictionary(k => k.Key, v => (object?)v.Value),
Extensions = exception.ValidationProblemDetailsExtended.Extensions.AsReadOnly(),
ErrorType = exception.GetType().Name
};
return Task.FromResult(errorLogInfo);
}
}
- Register your new service
using Pulse.FieldingTool.Api;
using Siemens.AspNet.MinimalApi.Sdk;
var webApi = new ServerlessMinimalWebApi();
webApi.RegisterServices = (service,
config) =>
{
// Domain service registrations
service.AddApi(config);
// Custom error handling
service.AddValidationProblemDetailsExtendedExceptionLogHandler()
};
webApi.MapEndpoints = endpoints =>
{
// Map api domain endpoints
endpoints.MapApi();
};
webApi.Run(args);
π Additional Resources
π€ Contributing
Contributions are welcome! Please submit pull requests or issues as needed.
π License
Please refer to the repository's license file.
| Product | Versions 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. |
-
net10.0
- Newtonsoft.Json (>= 13.0.4)
- Siemens.AspNet.ErrorHandling.Contracts (>= 7.4.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Siemens.AspNet.ErrorHandling:
| Package | Downloads |
|---|---|
|
Siemens.AspNet.MinimalApi.Sdk
A library which contains following functions: - Siemens.AspNet.MinimalApi.Sdk |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 7.5.0 | 219 | 5/12/2026 |
| 7.5.0-alpha.16 | 55 | 5/18/2026 |
| 7.5.0-alpha.15 | 51 | 5/18/2026 |
| 7.5.0-alpha.12 | 58 | 5/12/2026 |
| 7.5.0-alpha.11 | 53 | 5/12/2026 |
| 7.5.0-alpha.10 | 51 | 5/12/2026 |
| 7.5.0-alpha.3 | 62 | 5/11/2026 |
| 7.4.5 | 285 | 5/24/2026 |
| 7.4.4 | 34 | 5/18/2026 |
| 7.4.3 | 32 | 5/18/2026 |
| 7.4.2 | 2,493 | 5/11/2026 |
| 7.4.1 | 32 | 5/11/2026 |
| 7.4.0 | 4,523 | 5/6/2026 |
| 7.3.4 | 1,314 | 5/4/2026 |
| 7.3.3 | 951 | 5/4/2026 |
| 7.3.2 | 1,807 | 4/28/2026 |
| 7.3.1 | 2,196 | 4/24/2026 |
| 7.3.0 | 1,074 | 4/22/2026 |
| 7.2.0 | 1,494 | 4/22/2026 |
| 7.1.4 | 118 | 4/22/2026 |