HttpWebRequest.GetResponse()失败时如何获取错误信息


86

我正在初始化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)."
}

任何帮助,将不胜感激。

Answers:


151

使用HttpWebRequest和HttpWebResponse是否可能?

您可以让您的Web服务器简单地捕获异常文本并将其写入响应的主体,然后将状态代码设置为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的处理程序将清除它。这使我绊了几分钟。
索林2012年

@索林 从第一个语句开始的“流”将继续到下一个语句。就像在单行IF语句中一样,例如if(something)do-stuff-here;
RealityDysfunction 2014年

1
GetRequestStream并且GetResponse可以抛出异常
PreguntonCojoneroCabrón

@PreguntonCojoneroCabrón是的,看起来不太正确,是的。值得庆幸的是,Microsoft引入了HttpClient类,我怀疑这些天大多数人都在使用。msdn.microsoft.com/en-us/library/...
莫滕Nørgaard

8

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

Response属性WebException将是类型FtpWebResponse,您可以在其上检查其StatusCode属性以查看遇到的FTP错误

这是我最终得到的代码:

    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;
        }
    }

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();
}

0

您也可以使用此库,它将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类的任何人也都可以。

它不是灵丹妙药,但支持使用get和post以及JSON或XML请求和响应的异步和非异步方式进行get,post和delete。截至2020年6月21日,正在积极地进行维护


-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(); 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.