using System.Text.Json.Serialization; using System.Text.Json; using System.Text; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using MongoDB.Driver; using Microsoft.AspNetCore.Mvc; namespace Common.WebApi.Middlewares; public class ExceptionMiddleware { private readonly RequestDelegate _next; private readonly IHostEnvironment _host; private readonly ILogger _logger; private readonly JsonSerializerOptions _serializerOptions; public ExceptionMiddleware(RequestDelegate next, IHostEnvironment host, ILogger logger) { _logger = logger; _next = next; _host = host; _serializerOptions = new JsonSerializerOptions { Converters = { new JsonStringEnumConverter() }, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; } public async Task InvokeAsync(HttpContext httpContext) { try { //if (httpContext.Request.Method == "POST") //{ // using var streamreader = new System.IO.StreamReader(httpContext.Request.Body); // var body = await streamreader.ReadToEndAsync(); //} await _next(httpContext); } catch (Exception exc) { var title = exc.Message; var detail = "Unexpected error occured"; if (!_host.IsProduction()) detail = GetExceptionDetail(exc, false, true); if (exc is MongoException dbUpdateException) { title = "Database error"; if (!_host.IsProduction()) detail = GetExceptionDetail(dbUpdateException, true, true); } else if (exc.Source?.Contains("Mongo") == true) { title = "Database error"; if (!_host.IsProduction()) detail = GetExceptionDetail(exc, true, true); } var problemDetail = new ProblemDetails { Title = title, Detail = detail, Instance = httpContext.Request.Path, Status = StatusCodes.Status400BadRequest }; _logger.LogError("Необработанная ошибка: {Message}", exc.Message); httpContext.Response.StatusCode = StatusCodes.Status400BadRequest; httpContext.Response.ContentType = "application/problem+json"; await httpContext.Response.WriteAsync(JsonSerializer.Serialize(problemDetail, _serializerOptions)); } } private string GetExceptionDetail(Exception exc, bool includeMessage, bool includeInner) { var sb = new StringBuilder(); if (!string.IsNullOrWhiteSpace(exc.Message) && includeMessage) sb.Append(exc.Message); if (!string.IsNullOrWhiteSpace(exc.InnerException?.Message) && includeInner) { if (sb.Length > 0) sb.AppendLine(); sb.AppendLine("Inner:"); sb.Append(exc.InnerException.Message); } if (sb.Length > 0) sb.AppendLine(); sb.Append(exc.StackTrace); return sb.ToString(); } }