C# 如何从webclient获取状态代码?
我正在使用C# 如何从webclient获取状态代码?,c#,.net,vb.net,webclient,C#,.net,Vb.net,Webclient,我正在使用WebClient类将一些数据发布到web表单。我想获取表单提交的响应状态代码。到目前为止,我已经了解了如何在出现异常时获取状态代码 Catch wex As WebException If TypeOf wex.Response Is HttpWebResponse Then msgbox(DirectCast(wex.Response, HttpWebResponse).StatusCode) End If 但是,如果表
WebClient
类将一些数据发布到web表单。我想获取表单提交的响应状态代码。到目前为止,我已经了解了如何在出现异常时获取状态代码
Catch wex As WebException
If TypeOf wex.Response Is HttpWebResponse Then
msgbox(DirectCast(wex.Response, HttpWebResponse).StatusCode)
End If
但是,如果表单提交成功并且没有引发异常,那么我将不知道状态代码(200301302,…)
当没有抛出异常时,是否有方法获取状态代码
PS:我不喜欢使用httpwebrequest/httpwebresponse,我试过了。负责人不包括状态代码 如果我没有弄错的话,
WebClient
能够在一个方法调用中抽象出多个不同的请求(例如,正确处理100个连续响应、重定向等)。我怀疑如果不使用HttpWebRequest
和HttpWebResponse
,可能无法使用不同的状态代码
我突然想到,如果您对中间状态代码不感兴趣,您可以安全地假设最终状态代码在2xx(成功)范围内,否则,调用将不会成功
不幸的是,状态代码没有出现在
ResponseHeaders
字典中。您应该能够使用“client.ResponseHeaders[…]”调用,有关从响应中取回内容的示例,请参见此有一种使用反射的方法。它适用于.NET4.0。它访问私有字段,未经修改可能无法在.NET的其他版本中工作
我不知道为什么微软没有用一个属性公开这个字段
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;
}
如果您使用的是.Net 4.0(或更低版本):
如果您使用的是.Net 4.5.X或更高版本,请切换到:
您可以检查错误类型是否为
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!");
}
或
你应该使用
if (e.Status == WebExceptionStatus.ProtocolError)
{
HttpWebResponse response = (HttpWebResponse)ex.Response;
if (response.StatusCode == HttpStatusCode.NotFound)
System.Diagnostics.Debug.WriteLine("Not found!");
}
Erik的答案在Windows Phone上不起作用。以下是:
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;
}
}
}
至少在使用OpenReadAsync
时是这样;对于其他xxxAsync
方法,强烈建议仔细测试。框架沿着代码路径调用GetWebResponse;只需捕获并缓存响应对象
此代码段中的回退代码为200,因为真正的HTTP错误(500、404等)无论如何都会报告为异常。这个技巧的目的是捕获非错误代码,在我的具体案例304(未修改)中。因此,回退假设,如果状态代码不知何故不可用,至少不会出错。您可以尝试使用此代码从WebException或OpenReadCompletedEventArgs.Error获取HTTP状态代码。它也适用于Silverlight,因为SL没有定义WebExceptionStatus.ProtocolError
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;
}
以防其他人需要上述黑客的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()
开放系统
开放系统
开放系统.Net
类型WebClientEx()=
继承WebClient()
[]val可变m_响应:WebResponse
覆盖x.GetWebResponse(请求:WebRequest)=
x、 m_Resp HttpWebRequest)。AllowAutoRedirect这是我用来扩展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; }
}
返回的响应头是服务器头,如服务器、日期、pragma等。但是没有状态代码(200301404…)。对此感到抱歉,我有点惊讶地发现没有返回。如果您明确查找其他200系列消息(即201已创建-请参阅:),那么webrequest/ResponseEMS似乎是唯一的方法. :-/ 即使跳过了“中间”部分,如果能显式使用,那就太好了。@NormanH,我不反对。当涉及到状态代码时,WebClient似乎有点泄漏抽象。干杯非常感谢您的回答,它为我指出了获取响应头的正确方法-从WebException,而不是从WebClient.ResponseHeaders。是的,最好的方法实际上是在try-catch块中读取响应数据并捕获WebException。我这里遗漏了一些内容。“System.Exception”或“System.Net.Exception”均未包含“Error”的定义。如果调用成功,则不会出现异常(即返回2xx或3xx)。原来的海报是3xx,我在找204,其他人在找201。这并没有回答所问的问题。我不确定这个答案到目前为止是如何得到提升的,因为原始海报写道:“在没有引发异常的情况下,是否有某种方法可以获取状态代码?”我想现在没有必要进行下推表决。在Windows Phone上不起作用-GetWebResponse()只存在于两种参数化风格中。仍然+1。有趣的是它不起作用。对我来说很有用,在更高答案中的反射没有(.NET 4.5 windows 7和10 app)FWIW,这在windows Phone上是不可能的,因为windows Phone不允许通过反射访问私人成员注意BindingFlags要求“使用System.reflection;”不错,但是有办法获取子状态代码吗?例如403.1或403.2?响应对象具有SubStatusCode属性。这是为什么?OP明确指出:但是如果表单提交成功并且没有引发异常…
这对我来说非常有效,因为我正在寻找响应代码。很好的解决方案!请注意,[与HttpClient不同]4xx和5xx响应会导致在“response=base.GetWebResponse(request);”行引发WebException。您可以从异常中提取状态和响应(如果存在)。是。您仍然必须像正常情况一样捕获异常。但是,如果没有异常,这将暴露OP想要的内容。
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;
}
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()
/// <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
}