Improve exception handling with ProblemDetails responses

ExceptionHandlingMiddleware now returns structured ProblemDetails
responses for errors, including specific handling for
InvalidOperationException (400 Bad Request) and general exceptions
(500 Internal Server Error). Responses use "application/problem+json"
content type and include trace IDs. ProblemDetails support is also
registered in Program.cs.
This commit is contained in:
OlgunR
2026-04-21 13:18:59 +02:00
parent b7e66ab5f9
commit 612d8371d3
2 changed files with 19 additions and 17 deletions

View File

@@ -1,5 +1,4 @@
using System.Net;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
namespace DbFirst.API.Middleware;
@@ -20,33 +19,35 @@ public class ExceptionHandlingMiddleware
{
await _next(context);
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Domain validation error");
await WriteProblemAsync(context, StatusCodes.Status400BadRequest, "Eingabe ungültig", ex.Message);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled exception");
await WriteProblemDetailsAsync(context, ex);
await WriteProblemAsync(context, StatusCodes.Status500InternalServerError, "Serverfehler", ex.Message);
}
}
private static async Task WriteProblemDetailsAsync(HttpContext context, Exception ex)
private static async Task WriteProblemAsync(HttpContext context, int status, string title, string detail)
{
if (context.Response.HasStarted)
{
throw ex;
}
if (context.Response.HasStarted) return;
context.Response.Clear();
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
context.Response.StatusCode = status;
context.Response.ContentType = "application/problem+json";
var problem = new
var problem = new ProblemDetails
{
type = "https://tools.ietf.org/html/rfc9110#section-15.6.1",
title = "Serverfehler",
status = context.Response.StatusCode,
detail = ex.Message,
traceId = context.TraceIdentifier
Type = $"https://tools.ietf.org/html/rfc9110#section-{(status == 400 ? "15.5.1" : "15.6.1")}",
Title = title,
Status = status,
Detail = detail,
Extensions = { ["traceId"] = context.TraceIdentifier }
};
await context.Response.WriteAsync(JsonSerializer.Serialize(problem));
await context.Response.WriteAsJsonAsync(problem);
}
}