ASP.NET Core API结合MediatR的异常处理方案咨询
MediatR新手常见问题解答
一、是否需要在API控制器所有端点添加try-catch捕获MediatR异常?
不需要在每个控制器端点里写重复的try-catch块,推荐用全局异常处理机制统一处理,比如ASP.NET Core里的:
- 全局异常过滤器:实现
IExceptionFilter接口,在过滤器中捕获MediatR抛出的异常,根据异常类型返回对应HTTP状态码。 - 中间件:自定义异常处理中间件,拦截请求过程中抛出的异常,统一格式化响应。
举个实际场景的处理方式:
- 先定义业务异常类,比如:
public class BusinessException : Exception { public HttpStatusCode StatusCode { get; } public BusinessException(string message, HttpStatusCode statusCode = HttpStatusCode.BadRequest) : base(message) { StatusCode = statusCode; } }
- 在全局异常过滤器中处理:
public class GlobalExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext context) { if (context.Exception is BusinessException businessEx) { context.Result = new ObjectResult(new { Error = businessEx.Message }) { StatusCode = (int)businessEx.StatusCode }; context.ExceptionHandled = true; } // 其他异常类型处理(比如系统异常返回500) } }
- 在MediatR的Handler里抛出对应异常:
public class RegisterUserHandler : IRequestHandler<RegisterUserCommand, Unit> { public async Task<Unit> Handle(RegisterUserCommand request, CancellationToken cancellationToken) { if (!IsPasswordStrong(request.Password)) { throw new BusinessException("密码强度不足", HttpStatusCode.BadRequest); } // 注册逻辑... return Unit.Value; } }
这种方式既避免了重复代码,又能统一异常处理逻辑,比每个控制器写try-catch更高效。
二、全局Response类方案是否可行?
这个方案完全可行,而且是API开发中非常流行的统一响应格式方案,能让前端更方便地处理返回结果。针对你提供的代码,可以做一些小优化:
优化后的Response示例:
public class Response<T> where T : class { public T? Result { get; set; } public bool Success { get; set; } = false; // 默认设置为失败,成功时手动改为true public List<string> Errors { get; set; } = new(); // 用List方便添加错误信息 } // 针对无返回数据的场景,可添加非泛型版本 public class Response : Response<object> { }
使用建议:
- 在MediatR的Handler中直接返回Response
实例,比如查询用户的Handler:
public class GetUserByIdHandler : IRequestHandler<GetUserByIdQuery, Response<User>> { public async Task<Response<User>> Handle(GetUserByIdQuery request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.Id); if (user == null) { return new Response<User> { Errors = { "用户不存在" } }; } return new Response<User> { Success = true, Result = user }; } }
- 控制器中直接返回Handler的结果,无需额外处理:
[HttpGet("{id}")] public async Task<IActionResult> GetUser(int id) { var response = await _mediator.Send(new GetUserByIdQuery(id)); return response.Success ? Ok(response) : NotFound(response); }
这种方式能统一所有接口的返回格式,前端可以根据Success字段判断请求状态,Errors字段获取错误信息,Result获取数据,逻辑清晰。
内容的提问来源于stack exchange,提问作者mahmoud2 nasser2
相关产品推荐
相关产品推荐

