【问题标题】:Exception handling in Web APIWeb API 中的异常处理
【发布时间】:2015-01-24 02:08:26
【问题描述】:

在我的 Web API 项目中,我创建了处理实际数据处理操作的子项目(类库)。我的后端数据库是 DocumentDB。

我的问题是如何告诉我的 Web API 操作方法我在类库的数据方法中可能遇到的任何错误?一旦我的 Web API 方法知道错误,我就可以返回 Http status 500 或类似的东西,但我不确定在 catch 部分应该有什么(见下文)以及如何通知调用 Web API 方法遇到的错误?

--- Web API 方法---

public async Task<IHttpActionResult> DoSomething(Employee emp)
{
   var employeeRecord = await MyClassLibrary.DoSomethingWithEmployee(emp);

   // Here, I want to check for errors
}

--- 类库代码---

public static async Task<Employee> DoSomethingWithEmployee(Employee emp)
{
   try
   {
      // Logic here to call DocumentDB and create employee document
   }
   catch
   {
      // This is where I catch the error but how do I notify the calling Web API method that there was an error?
   }
}

【问题讨论】:

  • 你可以让异常冒出来。请注意,您的代码应尽可能避免异常。例外应该是真正例外的事情,例如数据库不可用。
  • @sam 我不会担心检查 DoSomething 中的 数据库异常类库异常。理想情况下,您不想在操作方法中处理每个异常。相反,让 GlobalExceptionHandler 处理这些错误。您可以在开源 MVC 项目中看到这种方法。 (见下面我的回答)

标签: c# asp.net-mvc asp.net-web-api2


【解决方案1】:

ASP.NET Web API 2.1 具有对未处理异常的全局处理的框架支持。

它允许用于自定义在发生未处理的应用程序异常时发送的 HTTP 响应。

所以,不要在类库中捕获异常。如果您需要在类库中记录异常,则将这些异常重新抛出到 Presentation。

WebApiConfig

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // ...

        config.Services.Replace(typeof (IExceptionHandler), 
            new GlobalExceptionHandler());
    }
}

GlobalExceptionHandler

public class GlobalExceptionHandler : ExceptionHandler
{
    public override void Handle(ExceptionHandlerContext context)
    {
        var exception = context.Exception;

        var httpException = exception as HttpException;
        if (httpException != null)
        {
            context.Result = new CustomErrorResult(context.Request,
                (HttpStatusCode) httpException.GetHttpCode(), 
                 httpException.Message);
            return;
        }

        // Return HttpStatusCode for other types of exception.

        context.Result = new CustomErrorResult(context.Request, 
            HttpStatusCode.InternalServerError,
            exception.Message);
    }
}

自定义错误结果

public class CustomErrorResult : IHttpActionResult
{
    private readonly string _errorMessage;
    private readonly HttpRequestMessage _requestMessage;
    private readonly HttpStatusCode _statusCode;

    public CustomErrorResult(HttpRequestMessage requestMessage, 
       HttpStatusCode statusCode, string errorMessage)
    {
        _requestMessage = requestMessage;
        _statusCode = statusCode;
        _errorMessage = errorMessage;
    }

    public Task<HttpResponseMessage> ExecuteAsync(
       CancellationToken cancellationToken)
    {
        return Task.FromResult(_requestMessage.CreateErrorResponse(
            _statusCode, _errorMessage));
    }
}

感谢 ASP.NET Web API 2: Building a REST Service from Start to Finishsource code

【讨论】:

    【解决方案2】:

    错误处理取决于您的逻辑以及您的 API 如何响应其使用者。

    基本上,您必须根据错误类型使用 HTTP 状态代码。

    在您的数据访问和业务层方法中,您可以依赖于返回类型。例如,在所有查询数据库的方法中,如果对象不存在,您可以返回 NULL,而在您的 Web API 中,如果方法返回 NULL,则只需返回 NotFound(),它将以 404 响应客户端.

    至于例外情况:

    您可以在业务和数据访问层中使用错误代码,并在您的 Web API 操作中检查这些代码。然后相应地返回一个合适的状态码。例如:如果存在与数据库的连接问题,则返回状态代码 500,如果用户没有以正确的格式提供所有必需的操作参数,则返回 400(错误请求)。

    如果您没有捕获任何其他异常,您可以使用@Win 描述的全局异常处理程序

    【讨论】:

      【解决方案3】:

      如果您想在控制台应用程序中截获并记录错误但仍将错误转发给调用者,只需在控制台应用程序中的 catch 语句末尾使用 throw;

      它将向调用者重新抛出相同的异常,因此您的应用程序可以知道“被调用者”和“调用者”中的异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-16
        • 2017-10-11
        • 2014-06-12
        • 2012-05-04
        • 2016-12-02
        • 2014-01-16
        • 1970-01-01
        相关资源
        最近更新 更多