// Xử lý các status code 4xx, 5xx
app.UseStatusCodePages();
// Hoặc redirect
app.UseStatusCodePagesWithRedirects("/Error/{0}");
// Hoặc re-execute
app.UseStatusCodePagesWithReExecute("/Error", "?statusCode={0}");
public class NotFoundException : Exception
{
public NotFoundException(string message) : base(message) { }
}
public class ValidationException : Exception
{
public IDictionary<string, string[]> Errors { get; }
public ValidationException(IDictionary<string, string[]> errors)
: base("Validation failed")
{
Errors = errors;
}
}
// Handler cho từng loại exception
public class NotFoundExceptionHandler : IExceptionHandler
{
public async ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
if (exception is not NotFoundException notFoundEx)
{
return false; // Không handle, để handler khác xử lý
}
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status404NotFound,
Title = "Not Found",
Detail = notFoundEx.Message,
Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4"
};
httpContext.Response.StatusCode = 404;
await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);
return true;
}
}
// Đăng ký theo thứ tự ưu tiên
builder.Services.AddExceptionHandler<NotFoundExceptionHandler>();
builder.Services.AddExceptionHandler<ValidationExceptionHandler>();
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
// ✅ Log với context
_logger.LogError(ex,
"Failed to process order {OrderId} for user {UserId}",
orderId, userId);
// ✅ Include request details
_logger.LogWarning(
"Rate limit exceeded for IP {IP} on endpoint {Endpoint}",
context.Connection.RemoteIpAddress,
context.Request.Path);