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 BankSampahApp.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");
|
|
}
|
|
} |