【问题标题】:WCF service returns incorrect Content-Length when using gzip encoding使用 gzip 编码时,WCF 服务返回不正确的 Content-Length
【发布时间】:2011-11-15 02:21:45
【问题描述】:

我有一个包含过滤文本框和列表框的网页。对文本框的修改会触发 AJAX 请求,该请求会返回一个值数组,用于填充列表框。

我有时会遇到这些调用失败的问题,具体取决于返回的数据大小。小数据返回会出错,大数据返回处理成功。

只有当我使用 jQuery 版本大于 4.2 时才会出现这个问题。如果我使用 jQuery 4.2 版,我没有问题。


这是调用的代码:
        jQuery.ajax(
            {
                cache: false,
                url: "../Services/CmsWebService.svc/GetAvailableVideosForCompany",
                type: "GET",
                complete: function (jqXHR, textStatus) {
                    var responseText = jqXHR.responseText;
                    jQuery('#debugConsole').text(responseText);
                    availableVideosPopulationState.isRunning = false;
                    setTimeout(populateAvailableVideosListBox, 100);
                },
                data: { "companyIdString": queryParameters.companyIdField,
                    "textFilter": queryParameters.filterText
                },
                dataType: 'json',
                error: function (jqXHR, textStatus, errorThrown) {
                    var errorString = 'Error thrown from ajax call: ' + textStatus + 'Error: ' + errorThrown;
                    alert(errorString);
                },
                success: function (data, textStatus, jqXHR) {
                    populateVideoListFromAjaxResults(data);
                }
            }
             );

如果返回两个元素,这里是调试控制台的内容:

{"d":[{"__type":"ListEntry:#WebsitePresentationLayer","Text":"SOJACKACT0310DSN1.mpg - [SOJACKACT0310DSN1]","Value":"5565_5565"},{"__type":"ListEntry:#WebsitePresentationLayer","Text":"SOJACKACT0310DSN1Q.mpg - [SOJACKACT0310DSN1Q]","Value":"5566_5566"}]}

但是如果返回一个元素:

{"d":[{"__type":"

所以,当然,我们得到一个“未终止的字符串常量”错误。


我使用 fiddler 进行了一些调查。

在所有响应(甚至是成功的响应)上,fiddler 都显示错误:

Fiddler 在会话 #n1 中检测到协议违规。

Content-Length mismatch: Response Header 表示 n2 个字节,但是 服务器发送了 n3 个字节。

如果响应标头指示的大小大于实际大小,则浏览器仍然可以解释结果。

如果响应头指示的大小小于实际大小,则浏览器无法解释结果。

显而易见的假设是响应处理代码读取Content-Length 标头,并且不会读取超出长度规定的任何数据。

我调查的下一步是比较 jQuery 版本 1.6.1(中断)和版本 1.4.2(未中断)的请求/响应标头。

jQuery 1.6.1 请求头:

GET /Web/Services/CmsWebService.svc/GetAvailableVideosForCompany?companyIdString=2&textFilter=3DSBDL2&_=1315869366142 HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://localhost:52200/Web/Admin/PlayerGroupEditor.aspx?groupid=76
Accept-Language: en-au
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Host: localhost:52200
Connection: Keep-Alive
Cookie: .ASPXAUTH=CE853BBD860F40F0026400610074006D006500640069006100310000002B5387799D71CC01002B5B5D62C771CC0100002F0000006B119589A7305098A560E57515498C56ECB332035F300427CDA2B28205D5E6B6

jQuery 1.6.1 响应头

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 12 Sep 2011 23:02:36 GMT
X-AspNet-Version: 4.0.30319
Content-Encoding: gzip
Content-Length: 140
Cache-Control: private
Content-Type: application/json; charset=utf-8
Connection: Close

这是我使用 jQuery 1.4.1 时的请求标头。请注意,Accept 标头与 jQuery 1.6.1 的值不同。

GET /Web/Services/CmsWebService.svc/GetAvailableVideosForCompany?_=1315870305531&companyIdString=2&textFilter=3DSBDL2 HTTP/1.1
Referer: http://localhost:52200/Web/Admin/PlayerGroupEditor.aspx?groupid=76
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*
Accept-Language: en-au
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Host: localhost:52200
Connection: Keep-Alive
Cookie: .ASPXAUTH=CE853BBD860F40F0026400610074006D006500640069006100310000002B5387799D71CC01002B5B5D62C771CC0100002F0000006B119589A7305098A560E57515498C56ECB332035F300427CDA2B28205D5E6B6

以及对 jQuery 4.1.1 的响应:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 12 Sep 2011 23:31:46 GMT
X-AspNet-Version: 4.0.30319
Content-Length: 131
Cache-Control: private
Content-Type: application/json; charset=utf-8
Connection: Close

所以明显的区别是,当通过 jQuery 1.6.1 进行调用时,响应使用 gzip 进行压缩,而当通过 jQuery 1.4.2 进行调用时,响应没有被压缩。


所以现在我可以做一个解决方案,即覆盖默认的 Accept 标头以确保它不包含"q=0.01" 字符串。 (我可以为"q=0.01" 找到的最佳解释是here,但我不明白为什么我的服务实现将其解释为严重压缩响应的请求。)
        // Make the AJAX call, passing in the company id and the filter string
        jQuery.ajax(
            {
                accepts: 'application/json, text/javascript, */*',
                cache: false,
                url: "../Services/CmsWebService.svc/GetAvailableVideosForCompany",
                type: "GET",
                complete: function (jqXHR, textStatus) {
                    var responseText = jqXHR.responseText;
                    jQuery('#debugConsole').text(responseText);
                    availableVideosPopulationState.isRunning = false;
                    setTimeout(populateAvailableVideosListBox, 100);
                },
                data: { "companyIdString": queryParameters.companyIdField,
                    "textFilter": queryParameters.filterText
                },
                dataType: 'json',
                error: function (jqXHR, textStatus, errorThrown) {
                    var errorString = 'Error thrown from ajax call: ' + textStatus + 'Error: ' + errorThrown;
                    alert(errorString);
                },
                success: function (data, textStatus, jqXHR) {
                    populateVideoListFromAjaxResults(data);
                }
            }
             );

那么在所有这些调查之后,剩下的问题是为什么当响应被 GZIP 压缩时,内容长度标头和实际内容长度之间存在差异?

我正在使用带有 webHttpBinding 的 WCF 服务。

【问题讨论】:

  • 你试过IE7和8模式吗?您是否尝试在其他地方托管该服务?
  • @Michael Sagalovich:我现在已经尝试过了。唯一的区别是 IE7 显示不同的错误消息:“Invalid JSON: {"d":[{"__type":"".
  • 您能否提供正在序列化的对象的类型以及它在服务端的序列化方式,我认为这可能很重要
  • {"d":[{"__type":" 是无效的 JSON。为什么服务返回无效的 JSON?
  • __type 值中是否有换行符?您可以使用 Fiddler(fiddler2.com/fiddler2) 检查 reponseText 并获得响应

标签: ajax wcf json gzip webhttpbinding


【解决方案1】:

首先——非常好的问题。这个问题为我提供了足够的信息来解决我的问题。

我遇到了类似的问题,并在此处发布了修复程序,以便它可以帮助某人。

  1. Ajax get & post 请求在 IE 中返回 null

  2. 在其他浏览器中工作正常,但在 fiddler 中看到“响应标头指示 n 字节,但服务器为请求发送了 nn 字节”消息。

显而易见的假设是响应处理 代码读取 Content-Length 标头,不再读取任何数据

我也这么认为!

在这种情况下,我很清楚一件事。 有东西篡改了请求/响应。 我尝试切换回旧版本的 jQuery(如您的问题中所述),但这没有帮助。

修复- 我打开了我的应用程序的网络配置,并通读了它。 模块中包含来自telerik 的'RadCompression Module',删除它后一切正常。

已知 RadCompression 模块存在错误,并通过压缩响应导致多个问题。

如果您遇到类似问题,请尝试检查可能会拦截您的请求/响应的内容。

【讨论】:

  • 我确实在使用 Telerik RadCompression 模块。您的回复提示我使用允许压缩的标头再次对此进行测试。现在它工作正常。我的理论是,这已通过 RadControls for ASP.NET 的版本升级得到修复。 (我现在使用的是 2011 年第二季度)。
  • 我在这里发现了一个错误报告:connect.microsoft.com/VisualStudio/feedback/details/597491/…
  • 实际上 - 它在 Visual Studio 2010 开发服务器上仍然存在问题。因此,我必须在我的开发 Web.Config 文件中禁用 RadCompression,但为生产站点启用 RadCompression。
  • 我使用的是 2011 年第三季度,遇到了这个问题。我没有尝试在 IIS 中运行我的 Web 应用程序,它都在 Cassini 中。感谢您提供信息。
  • 我今天在使用 Cassini 时遇到了这个问题。它至少与 Telerik RadCompression 和 Cassini 有关。 IISExpress 工作正常。
【解决方案2】:

Response Header indicated 140 bytes, but server sent 254 bytes 说了很多。是否与您使用的浏览器无关?如果是这样,我们可以说 IE 或 jQuery 1.4.3 以及 IE 中的后续版本在读取 Response Header 中指定的字节数后不会读取字节,而其他浏览器无论如何都会读取所有内容。

也有可能(但我几乎不相信这一点)响应标头仅针对 IE 请求形成错误。那你一定要看看IE和其他浏览器请求的区别和你的服务代码。也许您的服务专门处理 IE 请求?

计算 JSON 字符串中最后一个捕获的引号 (") 之后的字节数会很有趣。 114 可能吗?

【讨论】:

  • 感谢您的提问。我将调查重点放在了 Fiddlerre 结果上,并提出了更多信息。查看更新后的问题。
猜你喜欢
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
相关资源
最近更新 更多