¿Cómo obtener el código de estado de webclient?

Estoy usando la clase WebClient para publicar algunos datos en un formulario web. Me gustaría obtener el código de estado de la respuesta del envío del formulario. Hasta ahora he descubierto cómo obtener el código de estado si hay una excepción

 Catch wex As WebException If TypeOf wex.Response Is HttpWebResponse Then msgbox(DirectCast(wex.Response, HttpWebResponse).StatusCode) End If 

Sin embargo, si el formulario se envía correctamente y no se lanza ninguna excepción, no sabré el código de estado (200,301,302, …)

¿Hay alguna forma de obtener el código de estado cuando no se lanzan excepciones?

PD: prefiero no usar httpwebrequest / httpwebresponse

Probado. ResponseHeaders no incluye código de estado.

Si no me equivoco, WebClient es capaz de abstraer múltiples solicitudes distintas en una sola llamada a un método (por ejemplo, manejando correctamente 100 respuestas de Continuar, redirecciones y similares). Sospecho que sin usar HttpWebRequest y HttpWebResponse , un código de estado distinto puede no estar disponible.

Se me ocurre que, si no está interesado en códigos de estado intermedios, puede suponer con seguridad que el código de estado final está en el rango 2xx (correcto); de lo contrario, la llamada no sería exitosa.

Desafortunadamente, el código de estado no está presente en el diccionario ResponseHeaders .

Puede verificar si el error es de tipo WebException y luego inspeccionar el código de respuesta;

 if (e.Error.GetType().Name == "WebException") { WebException we = (WebException)e.Error; HttpWebResponse response = (System.Net.HttpWebResponse)we.Response; if (response.StatusCode==HttpStatusCode.NotFound) System.Diagnostics.Debug.WriteLine("Not found!"); } 

o

 try { // send request } catch (WebException e) { // check e.Status as above etc.. } 

Hay una manera de hacerlo usando la reflexión. Funciona con .NET 4.0. Accede a un campo privado y puede no funcionar en otras versiones de .NET sin modificaciones.

No tengo idea de por qué Microsoft no expuso este campo con una propiedad.

 private static int GetStatusCode(WebClient client, out string statusDescription) { FieldInfo responseField = client.GetType().GetField("m_WebResponse", BindingFlags.Instance | BindingFlags.NonPublic); if (responseField != null) { HttpWebResponse response = responseField.GetValue(client) as HttpWebResponse; if (response != null) { statusDescription = response.StatusDescription; return (int)response.StatusCode; } } statusDescription = null; return 0; } 

De otra manera:

 class BetterWebClient : WebClient { private WebRequest _Request = null; protected override WebRequest GetWebRequest(Uri address) { this._Request = base.GetWebRequest(address); if (this._Request is HttpWebRequest) { ((HttpWebRequest)this._Request).AllowAutoRedirect = false; } return this._Request; } public HttpStatusCode StatusCode() { HttpStatusCode result; if (this._Request == null) { throw (new InvalidOperationException(@"Unable to retrieve the status code, maybe you haven't made a request yet.")); } HttpWebResponse response = base.GetWebResponse(this._Request) as HttpWebResponse; if (response != null) { result = response.StatusCode; } else { throw (new InvalidOperationException(@"Unable to retrieve the status code, maybe you haven't made a request yet.")); } return result; } } 

La respuesta de Erik no funciona en Windows Phone como está. Lo siguiente hace:

 class WebClientEx : WebClient { private WebResponse m_Resp = null; protected override WebResponse GetWebResponse(WebRequest Req, IAsyncResult ar) { return m_Resp = base.GetWebResponse(Req, ar); } public HttpStatusCode StatusCode { get { if (m_Resp != null && m_Resp is HttpWebResponse) return (m_Resp as HttpWebResponse).StatusCode; else return HttpStatusCode.OK; } } } 

Al menos lo hace cuando se usa OpenReadAsync ; para otros métodos xxxAsync , se recomienda encarecidamente realizar pruebas cuidadosas. El marco llama a GetWebResponse en algún lugar a lo largo de la ruta del código; todo lo que uno necesita hacer es capturar y almacenar en caché el objeto de respuesta.

El código de reserva es 200 en este fragmento porque los errores genuinos HTTP – 500, 404, etc. – se informan como excepciones de todos modos. El objective de este truco es capturar códigos sin errores, en mi caso específico 304 (No modificado). Entonces, la alternativa asume que si el código de estado no está disponible, al menos no es erróneo.

Deberías usar

 if (e.Status == WebExceptionStatus.ProtocolError) { HttpWebResponse response = (HttpWebResponse)ex.Response; if (response.StatusCode == HttpStatusCode.NotFound) System.Diagnostics.Debug.WriteLine("Not found!"); } 

Solo en caso de que alguien más necesite una versión F # del hack descrito anteriormente.

 open System open System.IO open System.Net type WebClientEx() = inherit WebClient () [] val mutable m_Resp : WebResponse override x.GetWebResponse (req: WebRequest ) = x.m_Resp <- base.GetWebResponse(req) (req :?> HttpWebRequest).AllowAutoRedirect <- false; x.m_Resp override x.GetWebResponse (req: WebRequest , ar: IAsyncResult ) = x.m_Resp <- base.GetWebResponse(req, ar) (req :?> HttpWebRequest).AllowAutoRedirect <- false; x.m_Resp member x.StatusCode with get() : HttpStatusCode = if not (obj.ReferenceEquals (x.m_Resp, null)) && x.m_Resp.GetType() = typeof then (x.m_Resp :?> HttpWebResponse).StatusCode else HttpStatusCode.OK let wc = new WebClientEx() let st = wc.OpenRead("http://www.stackoverflow.com") let sr = new StreamReader(st) let res = sr.ReadToEnd() wc.StatusCode sr.Close() st.Close() 

Esto es lo que uso para expandir la funcionalidad de WebClient. StatusCode y StatusDescription siempre contendrán el código / descripción de respuesta más reciente.

  ///  /// An expanded web client that allows certificate auth and /// the retrieval of status' for successful requests ///  public class WebClientCert : WebClient { private X509Certificate2 _cert; public WebClientCert(X509Certificate2 cert) : base() { _cert = cert; } protected override WebRequest GetWebRequest(Uri address) { HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address); if (_cert != null) { request.ClientCertificates.Add(_cert); } return request; } protected override WebResponse GetWebResponse(WebRequest request) { WebResponse response = null; response = base.GetWebResponse(request); HttpWebResponse baseResponse = response as HttpWebResponse; StatusCode = baseResponse.StatusCode; StatusDescription = baseResponse.StatusDescription; return response; } ///  /// The most recent response statusCode ///  public HttpStatusCode StatusCode { get; set; } ///  /// The most recent response statusDescription ///  public string StatusDescription { get; set; } } 

Por lo tanto, puedes hacer una publicación y obtener un resultado a través de:

  byte[] response = null; using (WebClientCert client = new WebClientCert()) { response = client.UploadValues(postUri, PostFields); HttpStatusCode code = client.StatusCode; string description = client.StatusDescription; //Use this information } 

Debería poder utilizar la llamada “client.ResponseHeaders [..]”, consulte este enlace para ver ejemplos de cómo recuperar algo de la respuesta

Puede probar este código para obtener el código de estado HTTP de WebException o de OpenReadCompletedEventArgs.Error. También funciona en Silverlight porque SL no tiene definido WebExceptionStatus.ProtocolError.

 HttpStatusCode GetHttpStatusCode(System.Exception err) { if (err is WebException) { WebException we = (WebException)err; if (we.Response is HttpWebResponse) { HttpWebResponse response = (HttpWebResponse)we.Response; return response.StatusCode; } } return 0; }