Skip to content
bitzorcas
中EN

Reference

全局异常拦截与 RFC 9457 统一错误响应

掌握 BitzOrcas.Modern 企业级错误处理体系,深入 Result 业务流控、GlobalExceptionHandler 兜底拦截与 RFC 9457 Problem Details 标准映射。

Last updated

在生产环境中,最糟糕的错误体验莫过于两类极端:

  1. 直接暴露未捕获的黄页/堆栈(Stack Trace Leak):将 NullReferenceException 原始异常栈直接返回给前端,暴露敏感 SQL 结构与服务器路径,存在巨大安全隐患;
  2. 所有错误一律返回 200 OK + { code: -1, msg: "未知错误" }:破坏标准 HTTP 协议语义,导致 CDN、网关与客户端无法有效区分重试条件。

BitzOrcas.Modern 采用“分层错误治理 + RFC 9457 Problem Details 标准响应”:

  • 预期业务拒绝:由领域层返回强类型 Result.Failure(Error),由管道自动映射为对应的 4xx 状态码;
  • 非预期系统崩溃:由 ASP.NET Core IExceptionHandler 全局兜底拦截,屏蔽堆栈并返回标准的 500 结构。

错误治理与异常拦截全景

Result.SuccessResult.Failure(业务校验/冲突)发生非预期系统异常

1. 入站 HTTP 请求

2. 10 级管道流水线与 Handler

3. 执行结果评估

4. HTTP 200 OK (裸业务载荷)

5. 自动映射为 HTTP 400/404/409 (RFC 9457)

6. GlobalExceptionHandler (兜底捕获)

7. 结构化日志报警 + HTTP 500 Problem Details (屏蔽敏感堆栈)


第一步:领域层与 Handler 统一返回 Result

严禁在业务逻辑中 throw 自定义异常!所有业务分支统一使用强类型 Result:

CancelOrderCommandHandler.cs: 业务流控
using System.Threading;
using System.Threading.Tasks;
using BitzOrcas.Domain.Abstractions;
using BitzOrcas.Domain.Results;
public static class OrderErrors
{
public static readonly Error NotFound =
Error.NotFound("Order.NotFound", "指定的订单不存在。");
public static readonly Error CannotCancel =
Error.Conflict("Order.CannotCancel", "已完成或已发货的订单不可取消。");
}
public sealed class CancelOrderCommandHandler(
ICommandRepository<Order, string> orderRepository)
{
public async ValueTask<Result> Handle(CancelOrderCommand command, CancellationToken ct)
{
// 1. 加载聚合根
var orderResult = await orderRepository.FindAsync(command.OrderId, ct);
if (orderResult.IsFailure)
{
// 2. 资源不存在:返回强类型 NotFound 错误对象,绝不抛异常
return Result.Failure(orderResult.Error);
}
var order = orderResult.GetValueOrThrow();
// 3. 评估领域取消状态
var cancelResult = order.Cancel(command.Reason);
if (cancelResult.IsFailure)
{
// 4. 业务状态冲突:返回强类型 Conflict 错误对象
return cancelResult;
}
await orderRepository.SaveAsync(order, ct);
return Result.Success();
}
}

第二步:全局异常兜底拦截(GlobalExceptionHandler)

对于非预期的数据库宕机或空指针异常,由全局处理器统一收口:

GlobalExceptionHandler.cs: 兜底安全拦截
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
public sealed class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) : IExceptionHandler
{
public async ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
var traceId = httpContext.TraceIdentifier;
// 1. 结构化记录致命错误日志(包含完整堆栈供后台排查)
logger.LogError(exception, "未捕获的系统未预期异常已拦截,TraceId: {TraceId}", traceId);
// 2. 向客户端安全返回符合 RFC 9457 规范的 500 响应
httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
httpContext.Response.ContentType = "application/problem+json";
var problemDetails = new
{
type = "https://errors.bitzorcas.corp/internal-error",
title = "Internal Server Error",
status = 500,
detail = "系统发生未预期故障,请联系管理员并提供追踪号。",
traceId
};
await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);
return true;
}
}

总结

BitzOrcas 的分层错误体系提供了工业级的鲁棒性:

  • 无异常流控:业务分支 0 堆栈开销,性能极致;
  • 安全防泄密:对外彻底屏蔽物理堆栈与内部数据库路径;
  • 标准化响应:严格遵循 RFC 9457 Problem Details 规范。

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%