如何从webclient获取状态代码?

jul*_*lio 86 .net c# vb.net webclient

我正在使用WebClient该类将一些数据发布到Web表单.我想获取表单提交的响应状态代码.到目前为止,我已经发现如果有异常,如何获取状态代码

Catch wex As WebException
        If TypeOf wex.Response Is HttpWebResponse Then
          msgbox(DirectCast(wex.Response, HttpWebResponse).StatusCode)
            End If
Run Code Online (Sandbox Code Playgroud)

但是,如果表单提交成功并且没有抛出异常,那么我将不知道状态代码(200,301,302,...)

有什么方法可以在没有抛出异常时获取状态代码?

PS:我不想使用httpwebrequest/httpwebresponse

Hen*_*rtz 84

您可以检查错误是否类型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!");
}
Run Code Online (Sandbox Code Playgroud)

要么

try
{
    // send request
}
catch (WebException e)
{
    // check e.Status as above etc..
}
Run Code Online (Sandbox Code Playgroud)

  • 如果呼叫成功(即返回2xx或3xx),则不会有异常.原始海报正在寻找3xx,我正在寻找204,其他人正在寻找201.这不回答问题. (13认同)
  • 到目前为止,当原始海报上写道:"当没有异常抛出时,是否有某种方法可以获取状态代码?" 我现在认为现在没有任何意义. (3认同)
  • 我在这里遗漏了一些东西。“System.Exception”或“System.Net.Exception”都不包含“Error”的定义 (2认同)

Dmi*_* S. 30

有一种方法可以使用反射来实现.它适用于.NET 4.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;
}
Run Code Online (Sandbox Code Playgroud)

  • FWIW,这在Windows Phone上是不可能的,即使通过反射也不允许访问私有成员 (2认同)

Eri*_*ips 29

如果您使用.Net 4.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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果您使用的是.Net 4.5.X或更高版本,请切换到HttpClient:

var response = await client.GetAsync("http://www.contoso.com/");
var statusCode = response.StatusCode;
Run Code Online (Sandbox Code Playgroud)


kbr*_*ton 21

试了一下.ResponseHeaders不包含状态代码.

如果我没有弄错,WebClient能够在单个方法调用中抽象出多个不同的请求(例如正确处理100个继续响应,重定向等).我怀疑没有使用HttpWebRequestHttpWebResponse,可能无法使用不同的状态代码.

在我看来,如果您对中间状态代码不感兴趣,您可以安全地假设最终状态代码在2xx(成功)范围内,否则,呼叫将不会成功.

遗憾的是,状态代码不存在于ResponseHeaders字典中.

  • 似乎唯一的方法是webrequest/response (2认同)

Sev*_*yev 9

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

至少在使用时会这样做OpenReadAsync; 对于其他xxxAsync方法,强烈建议进行仔细测试.框架在代码路径的某个地方调用GetWebResponse; 所有人需要做的就是捕获并缓存响应对象.

此代码段中的回退代码为200,因为无论如何,正版HTTP错误(500,404等)都会报告为异常.这个技巧的目的是捕获非错误代码,在我的特定情况下304(未修改).因此,后备假设如果状态代码在某种程度上不可用,那么至少它是一个非错误的.