mai*_*ray 2 .net c# httpwebresponse system.net.webexception
我有一个桌面客户端,它通过 Http 与服务器端通信。当服务器在数据处理方面出现一些问题时,它会在 Http 响应正文中返回 JSON 中的错误描述,并带有正确的 Http 代码(主要是 HTTP-400)。
当我读到 HTTP-200 响应时,一切都很好,并且此代码有效:
using (var response = await httpRequest.GetResponseAsync(token))
{
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")))
{
return await reader.ReadToEndAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
但是当发生错误并且 WebException 被抛出并被捕获时,就会出现以下代码:
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
using (var response = (HttpWebResponse) ex.Response)
{
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream, Encoding.GetEncoding("utf-8")))
{
var json = reader.ReadToEnd();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经对它做了一些处理,也许可以让它工作,但接下来发生了:
response.ContentLength有效(184)但stream.Length为0,之后我无法读取json(它是"")我什至不知道在哪里看,因为一切看起来应该可以。
可能是什么问题?
经过一个月几乎每天的思考,我找到了解决方法。
问题是,WebException.Response.GetResponseStream()返回的流与请求期间获得的流不完全相同(现在找不到 msdn 的链接),当我们捕获异常并读取此流时,实际响应流丢失了(或类似的内容)我真的不知道,也无法在网上找到任何信息,除了查看现在开源的 CLRCore)。
要保存实际响应直到捕获,WebException您必须设置KeepAlive属性HttpRequest,瞧,您在捕获异常时会得到响应。所以工作代码如下所示:
try
{
var httpRequest = WebRequest.CreateHttp(Protocol + ServerUrl + ":" + ServerPort + ServerAppName + url);
if (HttpWebRequest.DefaultMaximumErrorResponseLength < int.MaxValue)
HttpWebRequest.DefaultMaximumErrorResponseLength = int.MaxValue;
httpRequest.ContentType = "application/json";
httpRequest.Method = method;
var encoding = Encoding.GetEncoding("utf-8");
if (httpRequest.ServicePoint != null)
{
httpRequest.ServicePoint.ConnectionLeaseTimeout = 5000;
httpRequest.ServicePoint.MaxIdleTime = 5000;
}
//----HERE--
httpRequest.KeepAlive = true;
//----------
using (var response = await httpRequest.GetResponseAsync(token))
{
using (var reader = new StreamReader(response.GetResponseStream(), encoding))
{
return await reader.ReadToEndAsync();
}
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
using (var response = (HttpWebResponse)ex.Response)
{
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream, Encoding.GetEncoding("utf-8")))
{
return reader.ReadToEnd();
//or handle it like you want
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道像这样保持所有连接是否有效,但由于它帮助我读取服务器的实际响应,我认为它可能会帮助遇到同样问题的人。
编辑:同样重要的是不要弄乱HttpWebRequest.DefaultMaximumErrorResponseLength.