Как получить код статуса от webclient?
Я использую WebClient
class для публикации некоторых данных в веб-форме. Я хотел бы получить код состояния ответа для отправки формы. До сих пор я узнал, как получить код состояния, если есть исключение
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 ответов Continue, перенаправления и т. д.). Я подозреваю, что без использования 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;
}