wake-up-neo.com

Wie erhalte ich den Statuscode vom Webclient?

Ich benutze die Klasse WebClient, um einige Daten in ein Webformular zu schreiben. Ich möchte den Antwortstatuscode des Formulars erhalten. Bisher habe ich herausgefunden, wie man den Statuscode erhält, wenn es eine Ausnahme gibt

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

Wenn das Formular jedoch erfolgreich gesendet und keine Ausnahme ausgelöst wird, weiß ich nicht, wie der Statuscode lautet (200, 301, 302, ...).

Gibt es eine Möglichkeit, den Statuscode abzurufen, wenn keine Ausnahmen ausgelöst werden?

PS: Ich bevorzuge es, httpwebrequest/httpwebresponse nicht zu verwenden

83
julio

Versuchte es aus. ResponseHeaders enthalten keinen Statuscode.

Wenn ich mich nicht irre, kann WebClient mehrere unterschiedliche Anforderungen in einem einzigen Methodenaufruf abstrahieren (z. B. 100 Continue-Antworten, Weiterleitungen und dergleichen korrekt verarbeiten). Ich vermute, dass ohne die Verwendung von HttpWebRequest und HttpWebResponse möglicherweise kein eindeutiger Statuscode verfügbar ist.

Wenn Sie sich nicht für Zwischenstatuscodes interessieren, können Sie davon ausgehen, dass der endgültige Statuscode im Bereich 2xx (erfolgreich) liegt. Andernfalls wäre der Anruf nicht erfolgreich.

Der Statuscode ist im Wörterbuch ResponseHeaders leider nicht vorhanden.

21
kbrimington

Sie können überprüfen, ob der Fehler vom Typ WebException ist, und dann den Antwortcode überprüfen.

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!");
}

oder

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

Es gibt eine Möglichkeit, dies durch Reflektion zu erreichen. Es funktioniert mit .NET 4.0. Es greift auf ein privates Feld zu und funktioniert in anderen .NET-Versionen möglicherweise nicht ohne Änderungen.

Ich habe keine Ahnung, warum Microsoft dieses Feld nicht mit einer Eigenschaft verfügbar gemacht hat.

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;
}
29
Dmitry S.

Wenn Sie .Net 4.0 (oder weniger) verwenden:

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;
        }
    }

Wenn Sie .Net 4.5.X oder neuer verwenden, wechseln Sie zu HttpClient :

var response = await client.GetAsync("http://www.contoso.com/");
var statusCode = response.StatusCode;
28
Erik Philips

Eriks Antwort funktioniert auf Windows Phone nicht so wie sie ist. Das Folgende tut:

class WebClientEx : WebClient
{
    private WebResponse m_Resp = null;

    protected override WebResponse GetWebResponse(WebRequest Req, IAsyncResult ar)
    {
        try
        {
            this.m_Resp = base.GetWebResponse(request);
        }
        catch (WebException ex)
        {
            if (this.m_Resp == null)
                this.m_Resp = ex.Response;
        }
        return this.m_Resp;
    }

    public HttpStatusCode StatusCode
    {
        get
        {
            if (m_Resp != null && m_Resp is HttpWebResponse)
                return (m_Resp as HttpWebResponse).StatusCode;
            else
                return HttpStatusCode.OK;
        }
    }
}

Zumindest bei Verwendung von OpenReadAsync; Für andere xxxAsync Methoden wird ein sorgfältiges Testen dringend empfohlen. Das Framework ruft GetWebResponse irgendwo im Codepfad auf. Alles, was Sie tun müssen, ist das Antwortobjekt zu erfassen und zwischenzuspeichern.

Der Fallback-Code in diesem Snippet ist 200, da echte HTTP-Fehler (500, 404 usw.) ohnehin als Ausnahmen gemeldet werden. Der Zweck dieses Tricks ist es, fehlerfreie Codes zu erfassen, in meinem speziellen Fall 304 (nicht modifiziert). Der Fallback geht also davon aus, dass der Statuscode, falls er nicht verfügbar ist, zumindest nicht fehlerhaft ist.

9
Seva Alekseyev

Du solltest benutzen

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

Nur für den Fall, dass jemand anderes eine F # -Version des oben beschriebenen Hacks benötigt.

open System
open System.IO
open System.Net

type WebClientEx() =
     inherit WebClient ()
     [<DefaultValue>] 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<HttpWebResponse> 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()
1
jpe

Dies ist, was ich zum Erweitern der WebClient-Funktionalität verwende. StatusCode und StatusDescription enthalten immer den aktuellsten Antwortcode/die aktuellste Beschreibung.

                /// <summary>
                /// An expanded web client that allows certificate auth and 
                /// the retrieval of status' for successful requests
                /// </summary>
                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;
                    }
                    /// <summary>
                    /// The most recent response statusCode
                    /// </summary>
                    public HttpStatusCode StatusCode { get; set; }
                    /// <summary>
                    /// The most recent response statusDescription
                    /// </summary>
                    public string StatusDescription { get; set; }
                }

Auf diese Weise können Sie einen Beitrag verfassen und das Ergebnis erhalten über:

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