NonInventPurchasingSystem/CPRNIMS.WebApi/Middleware/GlobalExceptionMiddleware.cs
2026-02-12 10:41:44 +08:00

90 lines
3.0 KiB
C#

using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.WebApi.Exceptions;
using System.Security.Claims;
using System.Text.Json;
namespace CPRNIMS.Middleware
{
public sealed class GlobalExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<GlobalExceptionMiddleware> _logger;
private readonly IWebHostEnvironment _env;
private readonly IServiceScopeFactory _scopeFactory;
public GlobalExceptionMiddleware(
RequestDelegate next,
ILogger<GlobalExceptionMiddleware> logger,
IWebHostEnvironment env,
IServiceScopeFactory scopeFactory)
{
_next = next;
_logger = logger;
_env = env;
_scopeFactory = scopeFactory;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled exception");
await LogToDatabaseAsync(context, ex);
await HandleResponseAsync(context, ex);
}
}
private async Task LogToDatabaseAsync(HttpContext context, Exception ex)
{
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<NonInventoryDbContext>();
var errorLog = new ErrorLog
{
Id = Guid.NewGuid(),
Path = context.Request.Path,
HttpMethod = context.Request.Method,
QueryString = context.Request.QueryString.Value,
StatusCode = context.Response.StatusCode,
ExceptionType = ex.GetType().FullName!,
Message = ex.Message,
StackTrace = ex.StackTrace,
UserId = context.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value,
IpAddress = context.Connection.RemoteIpAddress?.ToString(),
CreatedAt = DateTime.UtcNow
};
db.ErrorLogs.Add(errorLog);
await db.SaveChangesAsync();
}
private async Task HandleResponseAsync(HttpContext context, Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
AppException app => app.StatusCode,
ArgumentException => StatusCodes.Status400BadRequest,
UnauthorizedAccessException => StatusCodes.Status401Unauthorized,
_ => StatusCodes.Status500InternalServerError
};
var response = new
{
success = false,
message = _env.IsDevelopment()
? ex.Message
: "An unexpected error occurred"
};
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
}