处理异常:控制器应该返回什么

本文关键字:返回 什么 控制器 异常 处理 | 更新日期: 2023-09-27 18:19:49

我有一个Web API 2控制器操作,它返回用户列表

public List<User> GetAll()
{
    try
    {
        return _businessLogic.GetAll();
    }
    catch (Exception ex)
    {
        ExceptionHelper.HandleException(ex, _logger, ControllerContext);
    }
}
class ExceptionHelper {
    public static void HandleException(Exception ex, ILogger _logger, HttpControllerContext controllerContext) {
        _logger.LogError(ex);
        // If possible handle the exception here
        // Code for handling
        // Throw it again
        throw new HttpResponseException(
            controllerContext.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, errorMessagError)
        );
    }
}

C#编译器抱怨GetAll()中并非所有的代码路径都返回一个值。问题是,当发生异常时,我不想返回任何内容,因为HandleException会记录错误并再次抛出异常。我该如何明确表示我不想退货。

处理异常:控制器应该返回什么

通常,您应该处理异常,如果您知道如何处理,以及在处理异常后希望得到什么。由于异常是关于损坏状态的,所以您可以恢复状态,也不应该处理异常。

对于上面的示例,方法是完全删除异常处理。即:

public List<User> GetAll()
{
    return _businessLogic.GetAll();
}

GetAll方法中可能出现的问题:

  • 无法访问的数据源(基础设施问题)
  • 无效查询/EF模型等(代码问题)

无论如何,这些都非常适合HTTP500"内部服务器错误",因为这实际上是服务器错误。您越早从用户那里得到反馈,就越早修复它们。

通常的做法是记录异常。Web API允许您通过注入自己的IExceptionLogger实现来以自定义方式实现:

    public static void Register(HttpConfiguration config)
    {
        // ...
        // ApiNLogLogger is a custom logger, that uses NLog
        config.Services.Add(typeof(IExceptionLogger), new ApiNLogLogger());
    }

我们知道HandleException会再次抛出异常,但编译器不知道。因此,为了满足编译器验证,在不更改太多代码的情况下,只需在catch块中添加一个throw;即可。虽然无法访问此throw;,但编译器验证将通过,您的功能将按预期工作。示例如下:

public List<User> GetAll()
{
    try
    {
        return _businessLogic.GetAll();
    }
    catch (Exception ex)
    {
        ExceptionHelper.HandleException(ex, _logger, ControllerContext);
        throw;//Added throw to remove compilation error.
    }
}
class ExceptionHelper {
    public static void HandleException(Exception ex, ILogger _logger, HttpControllerContext controllerContext) {
        _logger.LogError(ex);
        // If possible handle the exception here
        // Code for handling
        // Throw it again
        throw new HttpResponseException(
            controllerContext.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, errorMessagError)
        );
    }
}

这样试试

public List<User> GetAll()
{
    List<User> result = new List<User>();
    try
    {
        result _businessLogic.GetAll();
    }
    catch (Exception ex)
    {
        ExceptionHelper.HandleException(ex, _logger, ControllerContext);
    }
    return result;
}

一个入口点。一个出口点。就我个人而言,我更喜欢在发生不好的事情时返回空列表,而不是返回null。