You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core API结合MediatR的异常处理方案咨询

MediatR新手常见问题解答

一、是否需要在API控制器所有端点添加try-catch捕获MediatR异常?

不需要在每个控制器端点里写重复的try-catch块,推荐用全局异常处理机制统一处理,比如ASP.NET Core里的:

  • 全局异常过滤器:实现IExceptionFilter接口,在过滤器中捕获MediatR抛出的异常,根据异常类型返回对应HTTP状态码。
  • 中间件:自定义异常处理中间件,拦截请求过程中抛出的异常,统一格式化响应。

举个实际场景的处理方式:

  1. 先定义业务异常类,比如:
public class BusinessException : Exception
{
    public HttpStatusCode StatusCode { get; }

    public BusinessException(string message, HttpStatusCode statusCode = HttpStatusCode.BadRequest)
        : base(message)
    {
        StatusCode = statusCode;
    }
}
  1. 在全局异常过滤器中处理:
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)
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:50:23