Updated ExceptionHandlingMiddleware to use the new Procedure property name when logging InsertObjectFailedException. Changed error title for BadRequestException to "Bad Procedure". Removed unused System.Text.Json using directive from InsertObjectProcedure.cs.
140 lines
5.2 KiB
C#
140 lines
5.2 KiB
C#
using DigitalData.Core.Exceptions;
|
|
using FluentValidation;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using ReC.Application.Common.Exceptions;
|
|
using System.Net;
|
|
using System.Text.Json;
|
|
|
|
namespace ReC.API.Middleware;
|
|
|
|
//TODO: Fix and use DigitalData.Core.Exceptions.Middleware
|
|
/// <summary>
|
|
/// Middleware for handling exceptions globally in the application.
|
|
/// Captures exceptions thrown during the request pipeline execution,
|
|
/// logs them, and returns an appropriate HTTP response with a JSON error details.
|
|
/// </summary>
|
|
[Obsolete("Use DigitalData.Core.Exceptions.Middleware")]
|
|
public class ExceptionHandlingMiddleware
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="ExceptionHandlingMiddleware"/> class.
|
|
/// </summary>
|
|
/// <param name="next">The next middleware in the request pipeline.</param>
|
|
/// <param name="logger">The logger instance for logging exceptions.</param>
|
|
public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
|
|
{
|
|
_next = next;
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes the middleware to handle the HTTP request.
|
|
/// </summary>
|
|
/// <param name="context">The HTTP context of the current request.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
try
|
|
{
|
|
await _next(context); // Continue down the pipeline
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await HandleExceptionAsync(context, ex, _logger);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles exceptions by logging them and writing an appropriate JSON response.
|
|
/// </summary>
|
|
/// <param name="context">The HTTP context of the current request.</param>
|
|
/// <param name="exception">The exception that occurred.</param>
|
|
/// <param name="logger">The logger instance for logging the exception.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
private static async Task HandleExceptionAsync(HttpContext context, Exception exception, ILogger logger)
|
|
{
|
|
context.Response.ContentType = "application/json";
|
|
|
|
ValidationProblemDetails? details = null;
|
|
|
|
switch (exception)
|
|
{
|
|
case BadRequestException badRequestEx:
|
|
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
|
|
details = new()
|
|
{
|
|
Title = "Bad Procedure",
|
|
Detail = badRequestEx.Message
|
|
};
|
|
break;
|
|
|
|
case ValidationException validationEx:
|
|
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
|
|
|
|
var errors = validationEx.Errors
|
|
.GroupBy(e => e.PropertyName, e => e.ErrorMessage)
|
|
.ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray());
|
|
|
|
details = new ValidationProblemDetails()
|
|
{
|
|
Title = "Validation failed",
|
|
Errors = validationEx.Errors
|
|
.GroupBy(e => e.PropertyName, e => e.ErrorMessage)
|
|
.ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray()),
|
|
};
|
|
|
|
break;
|
|
|
|
case NotFoundException notFoundEx:
|
|
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
|
details = new()
|
|
{
|
|
Title = "Not Found",
|
|
Detail = notFoundEx.Message
|
|
};
|
|
break;
|
|
|
|
case DataIntegrityException dataIntegrityEx:
|
|
context.Response.StatusCode = (int)HttpStatusCode.Conflict;
|
|
details = new()
|
|
{
|
|
Title = "Data Integrity Violation",
|
|
Detail = dataIntegrityEx.Message
|
|
};
|
|
break;
|
|
|
|
case InsertObjectFailedException insertFailedEx:
|
|
logger.LogError(
|
|
insertFailedEx,
|
|
"Insert operation failed during request processing. {procedure}",
|
|
JsonSerializer.Serialize(
|
|
insertFailedEx.Procedure,
|
|
options: new() { WriteIndented = true }
|
|
));
|
|
|
|
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
|
details = new()
|
|
{
|
|
Title = "Insert Operation Failed",
|
|
Detail = insertFailedEx.Message
|
|
};
|
|
break;
|
|
|
|
default:
|
|
logger.LogError(exception, "Unhandled exception occurred.");
|
|
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
|
details = new()
|
|
{
|
|
Title = "Internal Server Error",
|
|
Detail = "An unexpected error occurred. Please try again later."
|
|
};
|
|
break;
|
|
}
|
|
|
|
if (details is not null)
|
|
await context.Response.WriteAsJsonAsync(details);
|
|
}
|
|
} |