Frage Wie bekomme ich den Statuscode vom Webclient?


Ich benutze die WebClient Klasse, um einige Daten in ein Webformular zu stellen. Ich möchte den Antwortstatuscode der Formularübermittlung erhalten. Bisher habe ich herausgefunden, wie man den Statuscode bekommt, 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 übergeben wird und keine Ausnahme ausgelöst wird, kann ich den Statuscode nicht erkennen (200,301,302, ...)

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

PS: Ich möchte nicht httpwebrequest / httpwebresponse verwenden


75
2017-08-26 11:33


Ursprung


Antworten:


Ich habe es versucht. ResponseHeaders enthalten keinen Statuscode.

Wenn ich mich nicht irre, WebClient ist in der Lage, mehrere unterschiedliche Anforderungen in einem einzigen Methodenaufruf zu abstrahieren (z. B. korrekte Verarbeitung von 100 Weiter-Antworten, Umleitungen und dergleichen). Ich vermute das ohne zu benutzen HttpWebRequest und HttpWebResponse, ein eindeutiger Statuscode ist möglicherweise nicht verfügbar.

Es fällt mir ein, dass, wenn Sie nicht an Zwischenstatuscodes interessiert sind, Sie sicher davon ausgehen können, dass der endgültige Statuscode im Bereich 2xx (erfolgreich) ist, andernfalls wäre der Aufruf nicht erfolgreich.

Der Statuscode ist leider nicht in der ResponseHeaders Wörterbuch.


20
2017-08-26 11:43



Sie können überprüfen, ob der Fehler vom Typ ist WebException und dann den Antwortcode prü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..
}

73
2018-02-09 15:37



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

Ich habe keine Ahnung, warum Microsoft dieses Feld nicht mit einer Eigenschaft ausstellte.

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

27
2018-06-24 15:56



Ein anderer Weg:

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

23
2017-08-31 06:26



Eriks Antwort funktioniert auf Windows Phone nicht so wie es ist. Folgendes tut:

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

Zumindest bei der Verwendung OpenReadAsync; für andere xxxAsync Methoden, sorgfältige Tests werden dringend empfohlen. Das Framework ruft GetWebResponse irgendwo entlang des Codepfads auf; Sie müssen lediglich das Antwortobjekt erfassen und zwischenspeichern.

Der Fallback-Code ist 200 in diesem Snippet, da echte HTTP-Fehler - 500, 404 usw. - ohnehin als Ausnahmen gemeldet werden. Der Zweck dieses Tricks besteht darin, Nicht-Fehlercodes zu erfassen, in meinem speziellen Fall 304 (Nicht modifiziert). Das Fallback geht also davon aus, dass der Statuscode, wenn er irgendwie nicht verfügbar ist, zumindest nicht falsch ist.


6
2017-11-13 16:42



Du solltest benutzen

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

2
2017-08-21 09:33



Für den Fall, dass jemand anders 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
2017-11-25 18:13



Dies ist es, was ich für die Erweiterung der WebClient-Funktionalität verwende. StatusCode und StatusDescription enthalten immer den letzten Antwortcode / 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; }
                }

So können Sie einen Beitrag machen 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
2017-10-03 22:03



Sie sollten den Aufruf "client.ResponseHeaders [..]" verwenden können Verknüpfung Beispiele dafür, wie man Dinge aus der Antwort zurückbekommt


-1
2017-08-26 11:44



Sie können diesen Code versuchen, HTTP-Statuscode von WebException oder OpenReadCompletedEventArgs.Error abzurufen. Es funktioniert auch in Silverlight, weil SL WebExceptionStatus.ProtocolError nicht definiert hat.

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

-1
2017-12-09 09:54