.Net HttpWebRequest.GetResponse () déclenche une exception lorsque le code de statut http 400 (demande incorrecte) est renvoyé

Je suis dans une situation où, lorsque je reçois un code HTTP 400 du serveur, le serveur me dit tout à fait légalement ce qui n’allait pas avec ma demande (en utilisant un message dans le contenu de la réponse HTTP).

Toutefois, le .NET HttpWebRequest déclenche une exception lorsque le code d’état est 400.

Comment puis-je gérer cela? Pour moi, un 400 est complètement légal et plutôt utile. Le contenu HTTP contient des informations importantes, mais l’exception me jette sur mon chemin.

Ce serait bien s’il y avait un moyen de désactiver “jeter le code sans succès” mais si vous attrapez WebException, vous pouvez au moins utiliser la réponse:

using System; using System.IO; using System.Web; using System.Net; public class Test { static void Main() { WebRequest request = WebRequest.Create("http://csharpindepth.com/asd"); try { using (WebResponse response = request.GetResponse()) { Console.WriteLine("Won't get here"); } } catch (WebException e) { using (WebResponse response = e.Response) { HttpWebResponse httpResponse = (HttpWebResponse) response; Console.WriteLine("Error code: {0}", httpResponse.StatusCode); using (Stream data = response.GetResponseStream()) using (var reader = new StreamReader(data)) { ssortingng text = reader.ReadToEnd(); Console.WriteLine(text); } } } } } 

Vous voudrez peut-être encapsuler le bit “get me a response même s’il ne s’agit pas d’un code de réussite” dans une méthode séparée. (Je vous suggère de toujours lancer s’il n’y a pas de réponse, par exemple si vous ne pouviez pas vous connecter.)

Si la réponse d’erreur peut être importante (ce qui est inhabituel), vous voudrez peut-être modifier HttpWebRequest.DefaultMaximumErrorResponseLength pour vous assurer que vous obtenez toute l’erreur.

Je sais que cela a déjà été répondu il y a longtemps, mais j’ai fait une méthode d’extension pour aider d’autres personnes qui abordent cette question.

Code:

 public static class WebRequestExtensions { public static WebResponse GetResponseWithoutException(this WebRequest request) { if (request == null) { throw new ArgumentNullException("request"); } try { return request.GetResponse(); } catch (WebException e) { if (e.Response == null) { throw; } return e.Response; } } } 

Usage:

 var request = (HttpWebRequest)WebRequest.CreateHttp("http://invalidurl.com"); //... (initialize more fields) using (var response = (HttpWebResponse)request.GetResponseWithoutException()) { Console.WriteLine("I got Http Status Code: {0}", response.StatusCode); } 

J’ai rencontré des problèmes similaires lors de la tentative de connexion au service OAuth2 de Google.

J’ai fini par écrire le POST manuellement, sans utiliser WebRequest, comme ceci:

 TcpClient client = new TcpClient("accounts.google.com", 443); Stream netStream = client.GetStream(); SslStream sslStream = new SslStream(netStream); sslStream.AuthenticateAsClient("accounts.google.com"); { byte[] contentAsBytes = Encoding.ASCII.GetBytes(content.ToSsortingng()); SsortingngBuilder msg = new SsortingngBuilder(); msg.AppendLine("POST /o/oauth2/token HTTP/1.1"); msg.AppendLine("Host: accounts.google.com"); msg.AppendLine("Content-Type: application/x-www-form-urlencoded"); msg.AppendLine("Content-Length: " + contentAsBytes.Length.ToSsortingng()); msg.AppendLine(""); Debug.WriteLine("Request"); Debug.WriteLine(msg.ToSsortingng()); Debug.WriteLine(content.ToSsortingng()); byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToSsortingng()); sslStream.Write(headerAsBytes); sslStream.Write(contentAsBytes); } Debug.WriteLine("Response"); StreamReader reader = new StreamReader(sslStream); while (true) { // Print the response line by line to the debug stream for inspection. ssortingng line = reader.ReadLine(); if (line == null) break; Debug.WriteLine(line); } 

La réponse écrite dans le stream de réponses contient le texte d’erreur spécifique que vous recherchez.

En particulier, mon problème était que je mettais des lignes de fin entre des données encodées dans une URL. Quand je les ai sortis, tout a fonctionné. Vous pouvez peut-être utiliser une technique similaire pour vous connecter à votre service et lire le texte d’erreur de réponse réel.

Fait intéressant, le HttpWebResponse.GetResponseStream() que vous obtenez à partir de WebException.Response n’est pas le même que le stream de réponse que vous auriez reçu du serveur. Dans notre environnement, nous perdons les réponses réelles du serveur lorsqu’un code d’ état 400 HTTP est renvoyé au client à l’aide des objects HttpWebRequest/HttpWebResponse . D’après ce que nous avons vu, le stream de réponses associé à WebException's HttpWebResponse est généré sur le client et n’inclut aucun des éléments de réponse du serveur. Très frustrant, car nous voulons renvoyer au client la raison de la mauvaise demande.

Essayez ceci (c’est le code VB :-):

 Try Catch exp As WebException Dim sResponse As Ssortingng = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd End Try 

Une version asynchrone de la fonction d’extension:

  public static async Task GetResponseAsyncNoEx(this WebRequest request) { try { return await request.GetResponseAsync(); } catch(WebException ex) { return ex.Response; } }