Code d'état HTTP System.Net.WebException

153

Existe-t-il un moyen simple d'obtenir le code d'état HTTP à partir d'un System.Net.WebException?

Gilsham
la source

Réponses:

248

Peut-être quelque chose comme ça ...

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
la source
mais en cas d'exception "connectfailure" de webexception, j'obtiens une réponse nulle, dans ce cas comment puis-je obtenir le code httpstatus
Rusty
8
@rusty: Vous ne pouvez pas. S'il y a un échec de connexion, il n'y a aucun code d'état HTTP à obtenir.
LukeH
4
Si l'erreur est une ProtocolError, vous n'avez pas à vérifier la réponse pour null. Voir le commentaire dans l'exemple sur cette page MSDN
Andras Toth
5
@AndrasToth Mais des outils comme ReSharper vous donneront un avertissement si vous omettez la vérification de null. Et dans tous les cas, il est bon de coder de manière défensive.
Tom Lint
1
Comment obtenir la valeur du sous- statut HTTP ? Par exemple, 404.13 Content Length Too Large Reference : docs.microsoft.com/en-us/iis/configuration/system.webServer
...
27

En utilisant l' opérateur conditionnel nul ( ?.), vous pouvez obtenir le code d'état HTTP avec une seule ligne de code:

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

La variable statuscontiendra le HttpStatusCode. Lorsqu'il y a un échec plus général comme une erreur réseau où aucun code d'état HTTP n'est jamais envoyé, alors statussera nul. Dans ce cas, vous pouvez inspecter ex.Statuspour obtenir le fichier WebExceptionStatus.

Si vous souhaitez simplement qu'une chaîne descriptive se connecte en cas d'échec, vous pouvez utiliser l' opérateur de fusion nul ( ??) pour obtenir l'erreur appropriée:

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

Si l'exception est levée à la suite d'un code d'état HTTP 404, la chaîne contiendra "NotFound". En revanche, si le serveur est hors ligne, la chaîne contiendra "ConnectFailure" et ainsi de suite.

(Et pour quiconque souhaite savoir comment obtenir le code de sous-état HTTP. Ce n'est pas possible. Il s'agit d'un concept Microsoft IIS qui n'est enregistré que sur le serveur et jamais envoyé au client.)

Martin Liversage
la source
Vous ne savez pas si l' ?.opérateur était à l'origine nommé opérateur de propagation nul ou opérateur conditionnel nul lors de la version préliminaire. Mais le resharper Atlassian donne un avertissement pour utiliser l'opérateur de propagation nul dans de tels scénarios. Bon à savoir qu'il est également appelé opérateur conditionnel nul.
RBT
1
Un peu tard pour cette partie, mais juste un avertissement que l'opérateur conditionnel null est une fonctionnalité C # 6.0, il faut donc utiliser un compilateur qui le prend en charge. Réponse de Stack Overflow avec plus de détails . VS 2015+ l'a par défaut, mais si l'on utilise un type d'environnement de construction / déploiement autre que simplement "leur machine", d'autres choses devront peut-être être prises en compte.
CodeHxr du
9

cela ne fonctionne que si WebResponse est une 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
la source
pourquoi ne traiter que 401-Unauthorized au lieu de tous les codes d'état d'erreur HTTP possibles? c'est la pire réponse
ympostor
4
@ympostor Ceci n'est qu'un exemple. Tout développeur raisonnable comprend cela. Votre commentaire est le plus irréfléchi que j'ai jamais lu ici.
pr0gg3r
9

(Je me rends compte que la question est ancienne, mais elle fait partie des meilleurs résultats sur Google.)

Une situation courante dans laquelle vous souhaitez connaître le code de réponse est la gestion des exceptions. À partir de C # 7, vous pouvez utiliser la correspondance de modèles pour n'entrer dans la clause catch que si l'exception correspond à votre prédicat:

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

Cela peut facilement être étendu à d'autres niveaux, comme dans ce cas où le WebExceptionétait en fait l'exception interne d'un autre (et nous ne sommes intéressés que par 404):

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

Enfin: notez qu'il n'est pas nécessaire de relancer l'exception dans la clause catch lorsqu'elle ne correspond pas à vos critères, puisque nous n'entrons pas la clause en premier lieu avec la solution ci-dessus.

mini vous
la source
4

Vous pouvez essayer ce code pour obtenir le code d'état HTTP à partir de WebException. Cela fonctionne également dans Silverlight car SL n'a pas défini WebExceptionStatus.ProtocolError.

HttpStatusCode GetHttpStatusCode(WebException we)
{
    if (we.Response is HttpWebResponse)
    {
        HttpWebResponse response = (HttpWebResponse)we.Response;
        return response.StatusCode;
    }
    return null;
}
Sergey
la source
1
return 0? ou mieux HttpStatusCode?( nullable )?
Kiquenet
Est-ce que ça va marcher? var code = GetHttpStatusCode(ex); if (code != HttpStatusCode.InternalServerError) {EventLog.WriteEntry( EventLog.WriteEntry("MyApp", code, System.Diagnostics.EventLogEntryType.Information, 1);}
FMFF
Je ne comprends pas ce que vous vouliez faire dans cet exemple. Dans quels cas vous vouliez que l'événement soit enregistré?
Sergey
1

Je ne sais pas s'il y en a, mais s'il y avait une telle propriété, elle ne serait pas considérée comme fiable. A WebExceptionpeut être déclenché pour des raisons autres que les codes d'erreur HTTP, y compris de simples erreurs de réseau. Ceux-ci n'ont pas de code d'erreur http correspondant.

Pouvez-vous nous donner un peu plus d'informations sur ce que vous essayez d'accomplir avec ce code. Il existe peut-être un meilleur moyen d'obtenir les informations dont vous avez besoin.

JaredPar
la source