繁体   English   中英

无法从WebException获取ResponseStream

[英]Can't get ResponseStream from WebException

我有一个桌面客户端,通过Http与服务器端通信。 当服务器在数据处理方面存在一些问题时,它会在Http响应体中使用适当的Http代码(主要是HTTP-400)返回JSON中的错误描述。

当我阅读HTTP-200响应时,这个代码很有效:

 using (var response = await httpRequest.GetResponseAsync(token))
                {
                    using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")))
                    {
                        return await reader.ReadToEndAsync();
                    }
                }

但是当发生错误并抛出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();
                            }
                        }
                    }
                }
            }

我已经做了一些事情,可能让它工作,但下一个发生: response.ContentLength有效(184)但stream.Length是0,然后我无法读取json(它是"" )我不甚至知道在哪里看,因为一切看起来都应该有效。

可能是什么问题?

经过一个月的日常思考,我找到了解决方法。

问题是WebException.Response.GetResponseStream()返回的不是与请求期间获得的完全相同的流(现在找不到msdn的链接),当我们捕获异常并读取此流的实际响应时流丢失(或类似的东西,不知道并且无法在网上找到任何信息,除了查看现在是开源的CLRCore)。

要保存实际响应直到捕获WebException您必须在HttpRequest上设置KeepAlive属性,然后在捕获异常时获得响应。 所以工作代码看起来像这样:

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

我不知道是否保持所有连接都是这样的好,但是因为它帮助我阅读了服务器的实际响应,我认为这可能会帮助那些遇到同样问题的人。

编辑:重要的是不要乱用HttpWebRequest.DefaultMaximumErrorResponseLength

我记得以前遇到类似的问题,并且有一些与设置流的位置有关。 这是我之前阅读webResponse的解决方案之一 如果类似的方法适合您,请尝试: -

private ResourceResponse readWebResponse(HttpWebRequest webreq)
    {
        HttpWebRequest.DefaultMaximumErrorResponseLength = 1048576;
        HttpWebResponse webresp = null;// = webreq.GetResponse() as HttpWebResponse;
        var memStream = new MemoryStream();
        Stream webStream;
            try
            {
                webresp = (HttpWebResponse)webreq.GetResponse();
                webStream = webresp.GetResponseStream();
                byte[] readBuffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = webStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                    memStream.Write(readBuffer, 0, bytesRead);
            }
            catch (WebException e)
            {
                var r = e.Response as HttpWebResponse;
                webStream = r.GetResponseStream();
                memStream = Read(webStream);
                var wrongLength = memStream.Length;
            }


            memStream.Position = 0;
            StreamReader sr = new StreamReader(memStream);
            string webStreamContent = sr.ReadToEnd();

            byte[] responseBuffer = Encoding.UTF8.GetBytes(webStreamContent);
//......
//.......

希望这可以帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM