Error handling for ASP.NET Core APIs — exception middleware, ProblemDetails,
94
90%
Does it follow best practices?
Impact
100%
1.13xAverage score across 5 eval scenarios
Passed
No known issues
An insurance company is preparing for a compliance audit that requires all API errors to produce queryable, structured log entries. Their log management platform (Elasticsearch + Kibana) can index structured properties from log entries — but only when those properties are logged as discrete fields rather than as parts of a single interpolated string.
The current claims API codebase has a mix of logging styles: some code uses string interpolation inside log calls, some uses Console.WriteLine statements left over from debugging, and some correctly uses message templates. The compliance team needs every log statement in the exception handling layer to be fully structured so they can create dashboards filtering by claim ID, customer ID, HTTP method, or path without parsing free-text messages.
The audit also requires that the severity levels are appropriate: genuine unexpected errors must be logged as errors so they can trigger alerts, while known API errors (domain exceptions with a defined status code) should be logged at a lower severity.
You have been provided the current exception handling code below, which has several logging issues. Your task is to rewrite the logging throughout the handler so it passes a structured logging compliance review, and produce a brief compliance report explaining the changes.
Produce the following files in your working directory:
GlobalExceptionHandler.cs — the rewritten exception handler with correct structured logging throughoutcompliance_report.md — a short document (one section per original logging problem found) describing each issue, what was wrong, and how it was fixedExtract the following file before beginning.
=============== FILE: inputs/GlobalExceptionHandler.cs =============== using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc;
public class GlobalExceptionHandler : IExceptionHandler { private readonly ILogger<GlobalExceptionHandler> _logger;
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
{
_logger = logger;
}
public async ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
if (exception is OperationCanceledException)
{
Console.WriteLine($"Request to {httpContext.Request.Path} was cancelled");
httpContext.Response.StatusCode = 499;
return true;
}
var problemDetails = exception switch
{
ApiException apiEx => new ProblemDetails
{
Status = apiEx.StatusCode,
Title = apiEx.ErrorCode,
Detail = apiEx.Message,
Instance = httpContext.Request.Path
},
_ => new ProblemDetails
{
Status = 500,
Title = "INTERNAL_SERVER_ERROR",
Detail = "An unexpected error occurred.",
Instance = httpContext.Request.Path
}
};
if (exception is ApiException knownEx)
{
// Log known errors
_logger.LogError($"API error {knownEx.ErrorCode} occurred at {httpContext.Request.Path}");
}
else
{
// Log unknown errors
_logger.LogError($"Unhandled exception: {exception.Message} at path {httpContext.Request.Path} method {httpContext.Request.Method}");
}
httpContext.Response.StatusCode = problemDetails.Status ?? 500;
httpContext.Response.ContentType = "application/problem+json";
await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);
return true;
}}
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
skills
aspnet-error-handling
verifiers