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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user