// API.Core/Filters/GlobalExceptionFilter.cs using API.Core.Contracts.Common; using Domain.Exceptions; using FluentValidation; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; namespace API.Core; public class GlobalExceptionFilter(ILogger logger) : IExceptionFilter { public void OnException(ExceptionContext context) { logger.LogError(context.Exception, "Unhandled exception occurred"); switch (context.Exception) { case FluentValidation.ValidationException fluentValidationException: var errors = fluentValidationException .Errors.GroupBy(e => e.PropertyName) .ToDictionary( g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray() ); context.Result = new BadRequestObjectResult( new { message = "Validation failed", errors } ); context.ExceptionHandled = true; break; case ConflictException ex: context.Result = new ObjectResult( new ResponseBody { Message = ex.Message } ) { StatusCode = 409, }; context.ExceptionHandled = true; break; case NotFoundException ex: context.Result = new ObjectResult( new ResponseBody { Message = ex.Message } ) { StatusCode = 404, }; context.ExceptionHandled = true; break; case UnauthorizedException ex: context.Result = new ObjectResult( new ResponseBody { Message = ex.Message } ) { StatusCode = 401, }; context.ExceptionHandled = true; break; case ForbiddenException ex: context.Result = new ObjectResult( new ResponseBody { Message = ex.Message } ) { StatusCode = 403, }; context.ExceptionHandled = true; break; case Domain.Exceptions.ValidationException ex: context.Result = new ObjectResult( new ResponseBody { Message = ex.Message } ) { StatusCode = 400, }; context.ExceptionHandled = true; break; default: context.Result = new ObjectResult( new ResponseBody { Message = "An unexpected error occurred", } ) { StatusCode = 500, }; context.ExceptionHandled = true; break; } } }