使用哪个 WebException 状态代码?

Which WebException Status Code To Use?

我有一个向多个 API 发送请求的 c# 应用程序,但今天早些时候其中一个似乎关闭了一段时间并在我的异常处理程序中导致异常:

catch (WebException e)
{
    var statusCode = ((HttpWebResponse)e.Response).StatusCode;
    //Use status code and exception for reporting and handling.
}

这导致了一个问题,因为当时Exception没有Response,所以我试图得到什么都没有的StatusCode,结果抛出了一个NullPointerException。

我已经将其更改为此,以便在没有响应时尝试获取状态代码(无论如何我没有将响应用于状态代码以外的任何其他内容)。

catch (WebException e)
{
    //Try to get the status code from the exception, can fail somehow.
    HttpStatusCode statusCode;
    try
    {
        statusCode = (HttpStatusCode)e.Status;
    }
    catch(Exception innerE)
    {
        //Capture exceptions for logging
        //...
        //Set a default code to continue.
        statusCode = HttpStatusCode.InternalServerError;
    }
    //Use status code and exception for reporting and handling.
}

this answer 看来,您可以同时尝试响应的状态和异常的状态。

我的问题是我是否应该同时尝试两者,或者一个是否会被设置为另一个?

例如,为了测试我现在使用的代码,我能够手动抛出一个只有状态但没有响应的 WebException。

在任何情况下我都会收到没有异常状态的响应吗?或者,是否可能存在响应中的状态代码会更详细或与直接来自异常本身的状态代码不同的情况?

我正在使用基本 HttpWebRequest 拨打电话。

更新:

与我互动的API我无法控制,直到今天发生故障,我才发现可以无响应地返回。我将它手动设置为 500,以便在 catch 块中进一步处理我自己的错误,我的用户不知道那是我使用的。我只是问是否有一种检索 StatusCode 的方法是 better/different 而不是另一种方法。或者,如果我不应该依赖一种方法而不是另一种方法,我是否应该尝试两种方法以及更喜欢哪种方法?

我对类似情况的处理是,如果可能的话,尽可能多地从远程服务器获取信息。如果没有响应,catch 将手动分配一个状态码。

当您开始发回各种代码时,问题就来了,尤其是 5xx 系列服务器错误。我不喜欢 return 将他们的 500 作为我的问题。

在漫长的 运行 中,捕获的 Web 异常只会被记录到 ApiError table 中,我会 return 我认为最合适的响应代码,回退到 408 或者如果没有响应我会发回 "No Response".

的非标准 444 代码

这就是错误处理的美妙之处;你发现一个错误,尽力而为,并且可以转换为标准化的 HTTP 状态。

我遇到了同样的问题,在寻找解决方案时我意识到了一些事情。

  • WebExceptionStatus enum 不等同于您调用的 API 返回的 http 状态代码。相反,它是一个可能在 http 调用期间发生的错误的枚举。
  • 当您收到来自您的 API 的错误(400 到 599)时,将返回的 WebExceptionStatus 错误代码是 WebExceptionStatus.ProtocolError 又名数字 7 作为整数。
  • 当你需要获取api返回的响应体或真正的http状态码时,首先你需要检查WebExceptionStatus.Status是否为WebExceptionStatus.ProtocolError。然后你可以从 WebExceptionStatus.Response 得到真正的回应并阅读它的内容。

这是一个例子:

try
{
    ...
}
catch (WebException webException)
{
    if (webException.Status == WebExceptionStatus.ProtocolError)
    {
        var httpResponse = (HttpWebResponse)webException.Response;
        var responseText = "";
        using (var content = new StreamReader(httpResponse.GetResponseStream()))
        {
            responseText = content.ReadToEnd(); // Get response body as text
        }
        int statusCode = (int)httpResponse.StatusCode; // Get the status code
    }

    // Handle other webException.Status errors
}