namespace BuildingBlocks.ProblemDetails; using Exception; using Grpc.Core; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.WebUtilities; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; public static class Extensions { public static WebApplication UseCustomProblemDetails(this WebApplication app) { app.UseStatusCodePages(statusCodeHandlerApp => { statusCodeHandlerApp.Run(async context => { context.Response.ContentType = "application/problem+json"; if (context.RequestServices.GetService() is { } problemDetailsService) { await problemDetailsService.WriteAsync(new ProblemDetailsContext { HttpContext = context, ProblemDetails = { Detail = ReasonPhrases.GetReasonPhrase(context.Response.StatusCode), Status = context.Response.StatusCode } }); } }); }); app.UseExceptionHandler(exceptionHandlerApp => { exceptionHandlerApp.Run(async context => { context.Response.ContentType = "application/problem+json"; if (context.RequestServices.GetService() is { } problemDetailsService) { var exceptionHandlerFeature = context.Features.Get(); var exceptionType = exceptionHandlerFeature?.Error; if (exceptionType is not null) { (string Detail, string Title, int StatusCode) details = exceptionType switch { ConflictException => ( exceptionType.Message, exceptionType.GetType().Name, context.Response.StatusCode = StatusCodes.Status409Conflict ), ValidationException validationException => ( exceptionType.Message, exceptionType.GetType().Name, context.Response.StatusCode = (int)validationException.StatusCode ), BadRequestException => ( exceptionType.Message, exceptionType.GetType().Name, context.Response.StatusCode = StatusCodes.Status400BadRequest ), NotFoundException => ( exceptionType.Message, exceptionType.GetType().Name, context.Response.StatusCode = StatusCodes.Status404NotFound ), AppException => ( exceptionType.Message, exceptionType.GetType().Name, context.Response.StatusCode = StatusCodes.Status400BadRequest ), DbUpdateConcurrencyException => ( exceptionType.Message, exceptionType.GetType().Name, context.Response.StatusCode = StatusCodes.Status409Conflict ), RpcException => ( exceptionType.Message, exceptionType.GetType().Name, context.Response.StatusCode = StatusCodes.Status400BadRequest ), _ => ( exceptionType.Message, exceptionType.GetType().Name, context.Response.StatusCode = StatusCodes.Status500InternalServerError ) }; var problem = new ProblemDetailsContext { HttpContext = context, ProblemDetails = { Title = details.Title, Detail = details.Detail, Status = details.StatusCode } }; if (app.Environment.IsDevelopment()) { problem.ProblemDetails.Extensions.Add("exception", exceptionHandlerFeature?.Error.ToString()); } await problemDetailsService.WriteAsync(problem); } } }); }); return app; } }