在一处将自定义异常映射到HTTP异常

Question3r

在我的.NET Core Web API项目中,许多控制器端点都具有类似于此示例的代码

    public async Task<ActionResult<User>> UpdateUserUsernameAsync(/* DTOs */)
    {
        try
        {
            User user = null; // Update user here
            
            return Ok(user);
        }
        catch (EntityNotFoundException entityNotFoundException) // map not found to 404
        {
            return NotFound(entityNotFoundException.Message);
        }
        catch (EntityAlreadyExistsException entityAlreadyExistsException) // map duplicate name to 409
        {
            return Conflict(entityAlreadyExistsException.Message);
        }
        catch (Exception exception) // map any other errors to 500
        {
            return new StatusCodeResult(StatusCodes.Status500InternalServerError);
        }
    }

我想为控制器创建一个映射,以捕获异常并将其映射到HTTP响应,然后再将其发送回客户端。

4年前曾提出过类似的问题

ASP.NET Core Web API异常处理

在NestJs中,可以通过扩展基类来定义自己的映射,例如

export class MyCustomException extends HttpException {
  constructor() {
    super('My custom error message', HttpStatus.FORBIDDEN);
  }
}

从这里获取https://docs.nestjs.com/exception-filters#custom-exceptions

因此,基本上我想定义看起来像此示例代码的映射类(这仅显示了我的伪实现)

// Map MyCustomException to NotFound
public class MyCustomExceptionMapping<TCustomException> : IExceptionMapping<TCustomException>
{
    public ActionResult Map(TCustomException exception)
    {
        return NotFound(exception.Message);
    }
}

接下来,我可以将控制器端点方法清理为

public async Task<ActionResult<User>> UpdateUserUsernameAsync(/* DTOs */)
{
    User user = null; // Update user here

    return Ok(user);
}

每当引发异常时,API都会尝试查找正确的映射接口。否则,它将发送回500。

定义此类映射并避免对项目中的每个异常都进行大量切换非常好。

是否存在这样的东西?上一个问题接受的答案是否仍是最新的?

罗琳布鲁姆(Shloime Rosenblum)

使用异常过滤器,它将在控制器引发异常时被调用,您可以定义自定义响应。微软文档

public class MyExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        HttpStatusCode status;
        var message = "";

        var exceptionType = context.Exception.GetType();
        if (exceptionType is EntityNotFoundException)
        {
            status = HttpStatusCode.NotFound;
            message = context.Exception.Message;
        }
        else if (exceptionType is EntityAlreadyExistsException)
        {
            status = HttpStatusCode.Conflict;
            message = context.Exception.Message;
        }
        else
        {
           status = HttpStatusCode.InternalServerError;
           message = "Internal Server Error.";
        }

        //You can enable logging error

        context.ExceptionHandled = true;
        HttpResponse response = context.HttpContext.Response;
        response.StatusCode = (int)status;
        response.ContentType = "application/json";
        context.Result = new ObjectResult(new ApiResponse { Message = message, Data = null });
    }
}

要在所有控制器上使用过滤器,必须在Startup.cs的ConfigureServices方法中注册它

services.AddMvc(config =>
{
     config.Filters.Add(typeof(MyExceptionFilter));
})

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章