using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using System.Net; namespace BankSampahApp.Filters; /// /// Global exception filter untuk menangani error secara terpusat /// public class GlobalExceptionFilter : IExceptionFilter { private readonly ILogger _logger; private readonly IWebHostEnvironment _environment; /// /// Constructor dengan dependency injection /// /// Logger untuk logging /// Environment information public GlobalExceptionFilter( ILogger logger, IWebHostEnvironment environment) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _environment = environment ?? throw new ArgumentNullException(nameof(environment)); } /// /// Handle exception yang terjadi di aplikasi /// /// Exception context public void OnException(ExceptionContext context) { var exception = context.Exception; var requestId = context.HttpContext.TraceIdentifier; // Log the exception with details _logger.LogError(exception, "Unhandled exception occurred. RequestId: {RequestId}, Path: {Path}, Method: {Method}, User: {User}", requestId, context.HttpContext.Request.Path, context.HttpContext.Request.Method, context.HttpContext.User?.Identity?.Name ?? "Anonymous"); // Determine response based on request type if (IsApiRequest(context.HttpContext.Request)) { HandleApiException(context, exception, requestId); } else { HandleWebException(context, exception, requestId); } } /// /// Handle exception untuk API requests /// /// Exception context /// Exception yang terjadi /// Request ID private void HandleApiException(ExceptionContext context, Exception exception, string requestId) { var statusCode = GetStatusCodeFromException(exception); var includeDetails = _environment.IsDevelopment(); var response = new { Error = new { Message = includeDetails ? exception.Message : "An error occurred while processing your request.", RequestId = requestId, Details = includeDetails ? exception.ToString() : null, Type = exception.GetType().Name, Timestamp = DateTime.UtcNow } }; context.Result = new JsonResult(response) { StatusCode = (int)statusCode }; context.ExceptionHandled = true; } /// /// Handle exception untuk Web requests /// /// Exception context /// Exception yang terjadi /// Request ID private void HandleWebException(ExceptionContext context, Exception exception, string requestId) { var statusCode = GetStatusCodeFromException(exception); // Set status code context.HttpContext.Response.StatusCode = (int)statusCode; // Store exception details untuk error page context.HttpContext.Items["Exception"] = exception; context.HttpContext.Items["RequestId"] = requestId; // Redirect to error page var routeData = new RouteData(); routeData.Values["controller"] = "Home"; routeData.Values["action"] = "Error"; context.Result = new RedirectToRouteResult(routeData); context.ExceptionHandled = true; } /// /// Determine HTTP status code based on exception type /// /// Exception /// HTTP status code private static HttpStatusCode GetStatusCodeFromException(Exception exception) { return exception switch { ArgumentNullException => HttpStatusCode.BadRequest, ArgumentException => HttpStatusCode.BadRequest, UnauthorizedAccessException => HttpStatusCode.Unauthorized, NotImplementedException => HttpStatusCode.NotImplemented, TimeoutException => HttpStatusCode.RequestTimeout, _ => HttpStatusCode.InternalServerError }; } /// /// Check if request is API request /// /// HTTP request /// True if API request private static bool IsApiRequest(HttpRequest request) { // Check if request accepts JSON or has API path return request.Headers["Accept"].ToString().Contains("application/json") || request.Path.StartsWithSegments("/api") || request.Path.StartsWithSegments("/health"); } }