103

我可能在这里遗漏了一些明显的东西。

我正在使用HttpClientwhich throwsHttpRequestException包含StatusCode在消息字符串中。

我怎样才能访问它StatusCode


编辑:更多信息,我匆忙写了这个问题。

HttpClient用来访问我的 WebApi 项目中的另一个 API。是的,我知道我为什么要打电话EnsureSuccessStatusCode()。我想向下游传播一些错误,例如 404 和 403。

我想要的只是不断转变HttpRequestExceptionHttpResponseException使用 custom ExceptionFilterAttribute

不幸的是,HttpRequestException除了消息之外,没有任何我可以使用的额外信息。我希望以StatusCode原始(int 或 enum)形式发现。

看起来我可以:

  1. 使用消息切换状态码(bleh)
  2. 或者创建我的 EnsureSuccessStatusCode 版本并抛出实际可用的异常。
4

8 回答 8

42

状态代码作为字符串的一部分传递给,HttpRequestException因此您无法单独从此类异常中恢复它。

的设计System.Net.Http要求您访问HttpResponseMessage.StatusCode而不是等待异常。

http://msdn.microsoft.com/en-us/library/system.net.http.httpresponsemessage(v=vs.110).aspx

如果您现在遵循Microsoft 指南,请确保您清楚地了解它为什么要求您致电HttpResponseMessage.EnsureSucessStatusCode。如果您不调用该函数,则应该没有例外。

于 2014-03-06T07:42:50.493 回答
30

对于它的价值,这个家伙做了一些聪明的事情: https ://social.msdn.microsoft.com/Forums/vstudio/en-US/dc9bc426-1654-4319-a7fb-383f00b68def/c-httpresponsemessage-throws-exception-httprequestexception -webexception-the-remote-name?forum=csharpgeneral

在我需要异常状态属性的情况下,我可以这样做:

catch (HttpRequestException requestException)
{
    if (requestException.InnerException is WebException webException && webException.Status == WebExceptionStatus.NameResolutionFailure)
    {
        return true;
    }

    return false;
}
于 2016-08-10T20:24:13.833 回答
18

也许我来晚了:

从 .NET 5.0 开始, 如果异常表示不成功的结果,则该属性将具有一个值,否则为 null HttpRequestExceptionStatusCode所以你可以使用如下:

try
{
   // Your code
}
catch (HttpRequestException httpRequestException)
{
   if ((int)httpRequestException.StatusCode == 401)
   {
        // Show unauthorized error message
   }
   else 
   {
       // Other error message
   }
}

更多细节在这里

于 2021-01-03T15:07:13.063 回答
3

正如其他人所提到的,从 HttpRequestException 获取 StatusCode 不是一个好习惯,同样可以在检查 HttpResponseMessage.IsSuccessStatusCode 之后使用 HttpResponseMessage.StatusCode 预先完成

无论如何,如果由于某些约束/要求必须阅读 StatusCode,可以有两种解决方案

  1. 使用此处解释的自定义异常扩展了 HttpResponseMessage
  2. 破解 HttpRequestException.ToString 以获取 StatusCode,因为该消息是由 StatusCode 和 Rephase 修复的常量帖子。

下面是 System.Net.Http.HttpResponseMessage 中的代码,其中 SR.net_http_message_not_success_statuscode ="响应状态码不表示成功:{0} ({1})。"

public HttpResponseMessage EnsureSuccessStatusCode()
    {
        if (!this.IsSuccessStatusCode)
        {
            if (this.content != null)
            {
                this.content.Dispose();
            }
            throw new HttpRequestException(string.Format(CultureInfo.InvariantCulture, SR.net_http_message_not_success_statuscode, new object[]
            {
                (int)this.statusCode,
                this.ReasonPhrase
            }));
        }
        return this;
    }
于 2015-11-17T17:13:45.497 回答
1

这对我有用

var response = ex.Response;
var property = response.GetType().GetProperty("StatusCode");
if ( property != null && (HttpStatusCode)property.GetValue(response) == HttpStatusCode.InternalServerError)
于 2016-11-14T11:26:56.623 回答
0

对于 .Net Core 3.1,我无法使用 TanvirArjel 或 Lex Li 的解决方案。所以我手动调用 HttpClient 的 GetHttpAsync 方法并自己询问 Http 状态码。如果状态码返回“OK”,我会为返回的 Html 处理 HttpClient 的 Content 属性。

public async Task<string> GetHtml(string url)
{
    int retry = 3;

    while (retry > 0)
    {
        retry = retry - 1;

        try
        {   
            var result = await client.GetAsync(url);
            if (result.StatusCode != HttpStatusCode.OK)
            {
                switch (result.StatusCode)
                {
                    case HttpStatusCode.BadGateway:
                    case HttpStatusCode.BadRequest:
                    case HttpStatusCode.Forbidden:
                    case HttpStatusCode.ServiceUnavailable:
                    case HttpStatusCode.GatewayTimeout:
                        {
                            Global.Report($"CustomHttpClient: Temporary issue detected. Pausing to allow time to resolve.");
                            // Wait for temporary issue to resolve
                            await Task.Delay(120000);
                            continue;
                        }
                    default:
                        {
                            throw new Exception($"CustomHttpClient: Error {result.StatusCode}.");
                        }
                }
            }
            string response = await result.Content.ReadAsStringAsync();
            return response;
        }
        catch (Exception ex)
        {
            throw new Exception($"CustomHttpClient: Error downloading page => {url}. " + ex);
        }
    }

    throw new Exception($"CustomHttpClient: Temporary issue persists. Retries exhausted. Unable to download page => {url}.");
}
于 2021-04-12T15:53:25.150 回答
0

如果您需要从中提取状态代码HttpRequestException(例如:在应用程序异常处理程序中),请查看其他人的答案。

否则你可能会看一下HttpClient.GetAsync()方法。与诸如HttpClient.GetStringAsync()(返回简单数据类型并在出现问题时抛出异常)之类的方法不同,该方法每次都返回一个HttpResponseMessage对象,无论请求成功还是失败。

从那里您可以检查状态代码:

var response = await client.GetAsync(...);
if (!response.IsSuccessStatusCode)
{
    var statusCode = response.StatusCode;
    //throw an exception or something similar
}

var responseText = await response.Content.ReadAsStringAsync();
于 2021-10-26T09:18:31.447 回答
0

在.Net 6

    try
    {
        return await _httpClient.GetFromJsonAsync<YourType>("<url>", cancellationToken);
    }
    catch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.NotFound)   
    {
        // handle 404
    }
于 2021-12-12T19:41:36.290 回答