143 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C#
		
	
	
using Microsoft.AspNetCore.Mvc;
 | 
						|
using Microsoft.AspNetCore.Mvc.Filters;
 | 
						|
using System.Net;
 | 
						|
 | 
						|
namespace BpsRwApp.Filters;
 | 
						|
 | 
						|
/// <summary>
 | 
						|
/// Global exception filter untuk menangani error secara terpusat
 | 
						|
/// </summary>
 | 
						|
public class GlobalExceptionFilter : IExceptionFilter
 | 
						|
{
 | 
						|
    private readonly ILogger<GlobalExceptionFilter> _logger;
 | 
						|
    private readonly IWebHostEnvironment _environment;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Constructor dengan dependency injection
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="logger">Logger untuk logging</param>
 | 
						|
    /// <param name="environment">Environment information</param>
 | 
						|
    public GlobalExceptionFilter(
 | 
						|
        ILogger<GlobalExceptionFilter> logger,
 | 
						|
        IWebHostEnvironment environment)
 | 
						|
    {
 | 
						|
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
 | 
						|
        _environment = environment ?? throw new ArgumentNullException(nameof(environment));
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Handle exception yang terjadi di aplikasi
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="context">Exception context</param>
 | 
						|
    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);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Handle exception untuk API requests
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="context">Exception context</param>
 | 
						|
    /// <param name="exception">Exception yang terjadi</param>
 | 
						|
    /// <param name="requestId">Request ID</param>
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Handle exception untuk Web requests
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="context">Exception context</param>
 | 
						|
    /// <param name="exception">Exception yang terjadi</param>
 | 
						|
    /// <param name="requestId">Request ID</param>
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Determine HTTP status code based on exception type
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="exception">Exception</param>
 | 
						|
    /// <returns>HTTP status code</returns>
 | 
						|
    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
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Check if request is API request
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="request">HTTP request</param>
 | 
						|
    /// <returns>True if API request</returns>
 | 
						|
    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");
 | 
						|
    }
 | 
						|
} |