【问题标题】:How to get error information when HttpWebRequest.GetResponse() failsHttpWebRequest.GetResponse() 失败时如何获取错误信息
【发布时间】:2011-11-07 21:15:36
【问题描述】:

我正在启动一个 HttpWebRequest,然后检索它的响应。有时,我会收到 500(或至少 5##)错误,但没有说明。我可以控制两个端点,并希望接收端获得更多信息。例如,我想将异常消息从服务器传递到客户端。这可以使用 HttpWebRequest 和 HttpWebResponse 吗?

代码:

try
{
    HttpWebRequest webRequest = HttpWebRequest.Create(URL) as HttpWebRequest;
    webRequest.Method = WebRequestMethods.Http.Get;
    webRequest.Credentials = new NetworkCredential(Username, Password);
    webRequest.ContentType = "application/x-www-form-urlencoded";
    using(HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse)
    {
        if(response.StatusCode == HttpStatusCode.OK)
        {
            // Do stuff with response.GetResponseStream();
        }
    }
}
catch(Exception ex)
{
    ShowError(ex);
    // if the server returns a 500 error than the webRequest.GetResponse() method
    // throws an exception and all I get is "The remote server returned an error: (500)."
}

对此的任何帮助将不胜感激。

【问题讨论】:

  • 我只是补充一点,始终建议尽量减少由try 语句包裹的内容。在您的情况下,using 行之前的所有内容都可能写在外面。

标签: c# httpwebrequest httpwebresponse


【解决方案1】:

这可以使用 HttpWebRequest 和 HttpWebResponse 吗?

您可以让您的网络服务器简单地捕获异常文本并将其写入响应正文,然后将状态代码设置为 500。现在客户端在遇到 500 错误时会抛出异常,但您可以读取响应流并获取异常消息。

所以你可以捕捉到WebException,如果从服务器返回非 200 状态代码并读取其正文,则会抛出该代码:

catch (WebException ex)
{
    using (var stream = ex.Response.GetResponseStream())
    using (var reader = new StreamReader(stream))
    {
        Console.WriteLine(reader.ReadToEnd());
    }
}
catch (Exception ex)
{
    // Something more serious happened
    // like for example you don't have network access
    // we cannot talk about a server exception here as
    // the server probably was never reached
}

【讨论】:

  • 谢谢!需要注意的是,来自 using 语句内部的流在 using 语句之外将不可用,因为 WebResponse 的处理程序将清除它。这让我绊倒了几分钟。
  • @Thorin。第一条语句的“流”将继续到下一条语句。就像在单行 IF 语句中一样,例如 if(something)do-stuff-here;
  • GetRequestStreamGetResponse 可以抛出异常
  • @PreguntonCojoneroCabrón 是的,看起来不太对,是吗。值得庆幸的是,微软引入了 HttpClient 类,我怀疑这些天大多数人都在使用它。 msdn.microsoft.com/en-us/library/…
【解决方案2】:

我在尝试检查 FTP 站点上是否存在文件时遇到了这个问题。如果文件不存在,则在尝试检查其时间戳时会出错。但是我想通过检查它的类型来确保错误不是别的东西。

WebException 上的Response 属性将是FtpWebResponse 类型,您可以在其上检查其StatusCode 属性以查看您拥有的which FTP error

这是我最终得到的代码:

    public static bool FileExists(string host, string username, string password, string filename)
    {
        // create FTP request
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + host + "/" + filename);
        request.Credentials = new NetworkCredential(username, password);

        // we want to get date stamp - to see if the file exists
        request.Method = WebRequestMethods.Ftp.GetDateTimestamp;

        try
        {
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            var lastModified = response.LastModified;

            // if we get the last modified date then the file exists
            return true;
        }
        catch (WebException ex)
        {
            var ftpResponse = (FtpWebResponse)ex.Response;

            // if the status code is 'file unavailable' then the file doesn't exist
            // may be different depending upon FTP server software
            if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
            {
                return false;
            }

            // some other error - like maybe internet is down
            throw;
        }
    }

【讨论】:

    【解决方案3】:
    HttpWebRequest myHttprequest = null;
    HttpWebResponse myHttpresponse = null;
    myHttpRequest = (HttpWebRequest)WebRequest.Create(URL);
    myHttpRequest.Method = "POST";
    myHttpRequest.ContentType = "application/x-www-form-urlencoded";
    myHttpRequest.ContentLength = urinfo.Length;
    StreamWriter writer = new StreamWriter(myHttprequest.GetRequestStream());
    writer.Write(urinfo);
    writer.Close();
    myHttpresponse = (HttpWebResponse)myHttpRequest.GetResponse();
    if (myHttpresponse.StatusCode == HttpStatusCode.OK)
     {
       //Perform necessary action based on response
     }
    myHttpresponse.Close(); 
    

    【讨论】:

      【解决方案4】:

      我也遇到过类似的情况:

      我尝试使用 BasicHTTPBinding 读取原始响应以防使用 SOAP 服务的 HTTP 错误。

      但是,当使用GetResponseStream() 读取响应时,出现错误:

      流不可读

      所以,这段代码对我有用:

      try
      {
          response = basicHTTPBindingClient.CallOperation(request);
      }
      catch (ProtocolException exception)
      {
          var webException = exception.InnerException as WebException;
          var rawResponse = string.Empty;
      
          var alreadyClosedStream = webException.Response.GetResponseStream() as MemoryStream;
          using (var brandNewStream = new MemoryStream(alreadyClosedStream.ToArray()))
          using (var reader = new StreamReader(brandNewStream))
              rawResponse = reader.ReadToEnd();
      }
      

      【讨论】:

        【解决方案5】:

        您还可以使用this library,它将 HttpWebRequest 和 Response 包装到根据结果返回对象的简单方法中。它使用了这些答案中描述的一些技术,并且有大量的代码受到来自这个和类似线程的答案的启发。它会自动捕获任何异常,尽可能多地抽象出发出这些 Web 请求所需的样板代码,并自动反序列化响应对象。

        使用此包装器的代码示例如下所示:

            var response = httpClient.Get<SomeResponseObject>(request);
            
            if(response.StatusCode == HttpStatusCode.OK)
            {
                //do something with the response
                console.Writeline(response.Body.Id); //where the body param matches the object you pass in as an anonymous type.  
            }else {
                 //do something with the error
                 console.Writelint(string.Format("{0}: {1}", response.StatusCode.ToString(), response.ErrorMessage);
        
            }
        

        全面披露 这个库是一个免费的开源包装库,我是该库的作者。我没有从中赚钱,但多年来发现它非常有用,并且相信仍在使用 HttpWebRequest / HttpWebResponse 类的任何人也会。

        它不是灵丹妙药,但支持异步和非异步获取、发布、删除获取和发布以及 JSON 或 XML 请求和响应。截至 2020 年 6 月 21 日,它正在积极维护中

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-04
          • 1970-01-01
          • 2013-06-24
          • 1970-01-01
          • 1970-01-01
          • 2010-11-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多