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
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.
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..
}
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;
}
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;
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.
Du solltest benutzen
if (e.Status == WebExceptionStatus.ProtocolError)
{
HttpWebResponse response = (HttpWebResponse)ex.Response;
if (response.StatusCode == HttpStatusCode.NotFound)
System.Diagnostics.Debug.WriteLine("Not found!");
}
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()
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
}