Как получить код статуса от webclient?
Я использую WebClient
класс для публикации некоторых данных в веб-форме. Я хотел бы получить код состояния ответа на отправку формы. До сих пор я узнал, как получить код состояния, если есть исключение
Catch wex As WebException
If TypeOf wex.Response Is HttpWebResponse Then
msgbox(DirectCast(wex.Response, HttpWebResponse).StatusCode)
End If
однако если форма будет отправлена успешно и не будет выдано никаких исключений, то я не буду знать код состояния(200,301,302,...)
есть ли способ получить код состояния, когда нет никаких исключений?
PS: Я предпочитаю не используйте httpwebrequest / httpwebresponse
10 ответов:
попробовал. ResponseHeaders не включают код состояния.
если я не ошибаюсь,
WebClient
способен абстрагировать несколько различных запросов в одном вызове метода (например, правильно обрабатывать 100 ответов продолжения, перенаправления и т. п.). Я подозреваю, что без использованияHttpWebRequest
иHttpWebResponse
, уникальный код состояния может быть недоступна.мне кажется, что, если вас не интересуют промежуточные коды состояния, вы можете смело предположить окончательный код состояния находится в диапазоне 2xx (успешно), в противном случае вызов не будет успешным.
код состояния, к сожалению, нет в
ResponseHeaders
словарь.
вы можете проверить, если ошибка типа
WebException
а затем проверьте код ответа;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!"); }
или
try { // send request } catch (WebException e) { // check e.Status as above etc.. }
есть способ сделать это с помощью отражения. Он работает с .NET 4.0. Он обращается к закрытому полю и не может работать в других версиях .NET без изменений.
Я понятия не имею, почему Microsoft не предоставила это поле со свойством.
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; }
иначе:
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; } }
ответ Эрика не работает на Windows Phone как есть. Следующее назначение:
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; } } }
по крайней мере это делает при использовании
OpenReadAsync
; для другихxxxAsync
методы, тщательное тестирование было бы настоятельно рекомендуется. Платформа вызывает GetWebResponse где-то вдоль пути кода; все, что нужно сделать, это захватить и кэшировать объект ответа.резервный код составляет 200 в этом фрагменте, потому что подлинные ошибки HTTP-500, 404 и т. д. - В любом случае сообщаются как исключения. Цель из этого трюка состоит в том, чтобы захватить коды без ошибок, в моем конкретном случае 304 (не изменено). Поэтому резервный вариант предполагает, что если код состояния каким-то образом недоступен, по крайней мере, он не ошибочен.
вы должны использовать
if (e.Status == WebExceptionStatus.ProtocolError) { HttpWebResponse response = (HttpWebResponse)ex.Response; if (response.StatusCode == HttpStatusCode.NotFound) System.Diagnostics.Debug.WriteLine("Not found!"); }
на всякий случай кому-то еще нужна версия F# вышеописанного взлома.
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()
это то, что я использую для расширения функциональности WebClient. StatusCode и StatusDescription всегда будут содержать самый последний код ответа / описание.
/// <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; } }
таким образом, вы можете сделать сообщение и получить результат через:
byte[] response = null; using (WebClientCert client = new WebClientCert()) { response = client.UploadValues(postUri, PostFields); HttpStatusCode code = client.StatusCode; string description = client.StatusDescription; //Use this information }
вы должны быть в состоянии использовать "клиента.ResponseHeaders[..] "звоните, смотрите это ссылке для примеров получения материала обратно из ответа
вы можете попробовать этот код, чтобы получить код состояния HTTP из WebException или из OpenReadCompletedEventArgs.Ошибка. Он также работает в Silverlight, потому что SL не имеет WebExceptionStatus.Определена ошибка протокола.
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; }