Código de status HTTP System.Net.WebException

153

Existe uma maneira fácil de obter o código de status HTTP de um System.Net.WebException?

Gilsham
fonte

Respostas:

248

Talvez algo assim ...

try
{
    // ...
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError)
    {
        var response = ex.Response as HttpWebResponse;
        if (response != null)
        {
            Console.WriteLine("HTTP Status Code: " + (int)response.StatusCode);
        }
        else
        {
            // no http status code available
        }
    }
    else
    {
        // no http status code available
    }
}
LukeH
fonte
mas no caso de exceção "connectfailure" de WebException i obter uma resposta como null, nesse caso, como posso obter o código httpStatus
Rusty
8
@rusty: Você não pode. Se houver uma falha na conexão, não haverá código de status HTTP a ser obtido.
LukeH
4
Se o erro for um ProtocolError, você não precisará verificar se a resposta é nula. Veja o comentário no exemplo desta página do MSDN
Andras Toth
5
@AndrasToth Mas ferramentas como o ReSharper emitem um aviso se você omitir a verificação nula. E, de qualquer forma, é uma boa prática codificar defensivamente.
Tom Lint
1
Como obter o valor HTTP Substatus ? Por exemplo, 404.13 Referência de tamanho muito grande do conteúdo : docs.microsoft.com/en-us/iis/configuration/system.webServer/…
Kiquenet
27

Usando o operador nulo-condicional ( ?.), você pode obter o código de status HTTP com uma única linha de código:

 HttpStatusCode? status = (ex.Response as HttpWebResponse)?.StatusCode;

A variável statusconterá o HttpStatusCode. Quando houver uma falha mais geral, como um erro de rede em que nenhum código de status HTTP seja enviado, statusserá nulo. Nesse caso, você pode inspecionar ex.Statuspara obter o WebExceptionStatus.

Se você deseja apenas que uma string descritiva faça logon em caso de falha, use o operador coalescente-nulo ( ??) para obter o erro relevante:

string status = (ex.Response as HttpWebResponse)?.StatusCode.ToString()
    ?? ex.Status.ToString();

Se a exceção for lançada como resultado de um código de status HTTP 404, a sequência conterá "NotFound". Por outro lado, se o servidor estiver offline, a cadeia conterá "ConnectFailure" e assim por diante.

(E para quem quiser saber como obter o código de substatus HTTP. Isso não é possível. É um conceito do Microsoft IIS que é registrado apenas no servidor e nunca enviado ao cliente.)

Martin Liversage
fonte
Não tenho certeza se o ?.operador foi originalmente denominado operador de propagação nula ou operador condicional nulo durante a liberação da visualização. Mas o recarregador Atlassian emite um aviso para usar o operador de propagação nula em tais cenários. É bom saber que também é chamado de operador condicional nulo.
RBT
1
Um pouco atrasado para essa parte, mas é um aviso justo de que o operador condicional nulo é um recurso do C # 6.0, portanto, é necessário usar um compilador que o suporte. Resposta do Stack Overflow com mais detalhes . O VS 2015+ possui isso por padrão, mas se alguém estiver usando qualquer tipo de ambiente de construção / implantação que não seja apenas "sua máquina", outras coisas podem precisar ser levadas em consideração.
CodeHxr
9

isso funciona apenas se o WebResponse for um HttpWebResponse.

try
{
    ...
}
catch (System.Net.WebException exc)
{
    var webResponse = exc.Response as System.Net.HttpWebResponse;
    if (webResponse != null && 
        webResponse.StatusCode == System.Net.HttpStatusCode.Unauthorized)
    {
        MessageBox.Show("401");
    }
    else
        throw;
}
pr0gg3r
fonte
por que lidar apenas com 401-não autorizado em vez de todos os códigos de status de erro HTTP possíveis? esta é a pior resposta
ympostor 27/06
4
@ympostor Este é apenas um exemplo. Qualquer desenvolvedor razoável entende isso. Seu comentário é o mais impensado que eu já li aqui.
pr0gg3r
9

(Sei que a pergunta é antiga, mas está entre os principais hits do Google.)

Uma situação comum em que você deseja saber o código de resposta está no tratamento de exceções. A partir do C # 7, você pode usar a correspondência de padrões para realmente inserir apenas a cláusula catch se a exceção corresponder ao seu predicado:

catch (WebException ex) when (ex.Response is HttpWebResponse response)
{
     doSomething(response.StatusCode)
}

Isso pode ser facilmente estendido para outros níveis, como neste caso em que na WebExceptionverdade era a exceção interna de outro (e estamos interessados ​​apenas em 404):

catch (StorageException ex) when (ex.InnerException is WebException wex && wex.Response is HttpWebResponse r && r.StatusCode == HttpStatusCode.NotFound)

Finalmente: observe como não há necessidade de lançar novamente a exceção na cláusula catch quando ela não corresponde aos seus critérios, pois não inserimos a cláusula em primeiro lugar com a solução acima.

miniyou
fonte
4

Você pode tentar esse código para obter o código de status HTTP do WebException. Também funciona no Silverlight porque o SL não possui WebExceptionStatus.ProtocolError definido.

HttpStatusCode GetHttpStatusCode(WebException we)
{
    if (we.Response is HttpWebResponse)
    {
        HttpWebResponse response = (HttpWebResponse)we.Response;
        return response.StatusCode;
    }
    return null;
}
Sergey
fonte
1
return 0? ou melhor HttpStatusCode?( anulável )?
Kiquenet 23/03
Isso vai funcionar? var code = GetHttpStatusCode(ex); if (code != HttpStatusCode.InternalServerError) {EventLog.WriteEntry( EventLog.WriteEntry("MyApp", code, System.Diagnostics.EventLogEntryType.Information, 1);}
FMFF 30/11
Não consigo entender o que você queria fazer nesta amostra. Em quais casos você deseja que o evento seja registrado?
Sergey
1

Não tenho certeza se existe, mas se houvesse essa propriedade, não seria considerada confiável. A WebExceptionpode ser acionada por outros motivos que não os códigos de erro HTTP, incluindo simples erros de rede. Aqueles não têm esse código de erro http correspondente.

Você pode nos dar um pouco mais de informações sobre o que você está tentando realizar com esse código. Pode haver uma maneira melhor de obter as informações necessárias.

JaredPar
fonte