I have a web page containing a filtering text box and a list box. Modifications to the text box trigger an AJAX request, which returns an array of values with which to populate the list box.
I had problems with these calls failing sometimes, dependent on the size of the data returned. Small-sized returned data would result in an error, large-size data was returned and processed succesfully.
This problem only happens when I use a jQuery version greater than 4.2. If I use jQuery version 4.2, I don't have the problem.
Here is the code of the call:
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);
}
}
);
Here is the contents of the debug console if two elements are returned:
{"d":[{"__type":"ListEntry:#WebsitePresentationLayer","Text":"SOJACKACT0310DSN1.mpg - [SOJACKACT0310DSN1]","Value":"5565_5565"},{"__type":"ListEntry:#WebsitePresentationLayer","Text":"SOJACKACT0310DSN1Q.mpg - [SOJACKACT0310DSN1Q]","Value":"5566_5566"}]}
But if one element is returned:
{"d":[{"__type":"
So, of course, we get an "Unterminated String Constant" error.
I have done some investigation using fiddler.
On all responses (even the succesful ones), fiddler displayed an error:
Fiddler has detected a protocol violation in session #n1.
Content-Length mismatch: Response Header indicated n2 bytes, but server sent n3 bytes.
If the response header indicates a size greater than than actual size, then the results could still be interpreted by the browser.
If the response header indicates a size less than the actual size, then the browser could not interpret the results.
The obvious assumption to make there is that the response handling code reads the Content-Length
header and doesn't read any more data than that stipulated in the length.
The next step in my investigation is to compare the request/response headers for jQuery version 1.6.1 (which breaks) and version 1.4.2 (which does not break).
jQuery 1.6.1 request header:
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 response headers
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
And here is the request header when I use jQuery 1.4.1. Notice that the Accept
header is different from the jQuery 1.6.1 value.
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
And the response back to 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
So the obvious difference is that when the call is made via jQuery 1.6.1 the response is compressed using gzip, and when the call is made via jQuery 1.4.2 the response is not compressed.
So now I can do a work around solution, which is to override the default Accept header to ensure it does not contain the
"q=0.01"
string. (The best explanation I can find for "q=0.01"
is here, but I fail to see why my service implementation is interpreting this as a request to zip up the response badly.)
// 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);
}
}
);
So after all this investigation, the remaining question is why is there a disparity between the content length header and the actual content length when the response is GZIP compressed?
I'm using a WCF service with webHttpBinding.