using System.ComponentModel.DataAnnotations; using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.AspNetCore.Mvc; namespace SWAD.API.Middlewares; /// /// DONT TOUCH THAT!!! Generate good messages for responses and handle to logger exceptions /// /// /// /// public class ExceptionMiddleware(ILogger logger, IWebHostEnvironment env, RequestDelegate next) { private const string DefaultMessage = "An unexpected error has occurred, dude."; private const string ResponseStartedMessage = "The response has already started, the http status code middleware will not be executed."; public async Task InvokeAsync(HttpContext httpContext) { try { await next(httpContext); } catch (Exception e) { if (httpContext.Response.HasStarted) { logger.LogWarning(ResponseStartedMessage); throw; } var id = string.IsNullOrEmpty(httpContext?.TraceIdentifier) ? Guid.NewGuid().ToString() : httpContext.TraceIdentifier; logger.LogError($"An exception was thrown during the request, dude. " + $"{id} \n{(env.IsDevelopment() ? "strcstart:\n" + e : e.GetType().Name) + e.StackTrace + e.Source + e.InnerException}"); // logger.LogError($"An exception was thrown during the request, dude. " + // $"{id} \n{(env.IsDevelopment() ? "strcstart:\n" + e : e.GetType().Name)}"); await ProblemExceptionResponse(httpContext!, e, id); } } private async Task ProblemExceptionResponse(HttpContext httpContext, Exception e, string id) { //Create problem var problem = new ProblemDetails { Title = DefaultMessage, Status = StatusCodes.Status500InternalServerError }; //Add stacktrace if env is development if (env.IsDevelopment()) { problem.Detail = $"{e.Message} in {e.GetType().Name}"; var lines = new List { "Next strings is stacktrace. Enjoy, dude :)", "strcstart:" } .Concat(e.StackTrace!.Split("\r\n").Select(e => e.TrimStart())); problem.Extensions.Add(new KeyValuePair("StackTrace", lines)); } else { problem.Detail = $"{e.Message} in {e}"; } switch (e) { case NotImplementedException: problem.Status = StatusCodes.Status501NotImplemented; break; case ValidationException ve: return; } var jsonResponse = JsonSerializer .Serialize(problem, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); httpContext.Response.StatusCode = problem.Status ?? StatusCodes.Status500InternalServerError; httpContext.Response.ContentType = "application/problem+json"; await httpContext.Response .WriteAsync(jsonResponse); } }