Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Firefox 3.0 XmlHttpRequest Default Content-Type change


:P
On this page:
I just installed beta 4 of FireFox 3.0 and checked a few of my application that use AJAX to make sure if things would still work properly. Specifically I ran through samples for the Data Resource provider front end which uses extensive AJAX callbacks to display data and incremental UI. And I noticed that this code simply didn't work - all the callbacks to the server end up failing with the server complaining about a missing POST variable that is actually being sent from the client. Checked with all other browsers I have installed (FireFox 2, IE 7/8, Safari and Opera) and they all works fine, but only FireFox 3.0 chokes on this code.

After some investigation I found the problem in my JsonCallbackMethodProcessor code in the West Wind Ajax Toolkit, which is maybe a bit brittle:

else if (contentType == STR_UrlEncodedContentType && Request.Params["CallbackMethod"] != null)

where

public const string STR_UrlEncodedContentType = "application/x-www-form-urlencoded";

This has always worked as a check for seeing if content is URL encoded, but FireFox 3.0 adds an explicit character set to the content-type string:

POST /wwHoverpanel/SimpleMethodCallbacks.aspx HTTP/1.1
Host: rasnote
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.11; .NET CLR 2.0.50727) Gecko/20071127 Firefox/2.0.0.11
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,de-DE;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Pragma: no-cache, no-cache
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer:
http://rasnote/wwHoverpanel/SimpleMethodCallbacks.aspx
Content-Length: 114

CallbackMethod=HelloWorld&Parm1=%22John%20Doe%22&CallbackParmCount=1&__WWEVENTCALLBACK=Proxy&__WWEVENTTARGET=Page&

The additional character set of course breaks the above code and so all callbacks are broken. Easy thing to miss, but it's probably a good idea in general when looking for content types to use .StartsWith() or explicitly strip out the character set with RegEx to pick up the content type only.

else if (contentType.StartsWith( STR_UrlEncodedContentType ) && Request.Params["CallbackMethod"] != null)

There are a few other places where this needed to be adjusted as well - the JsonCallbackProcessor also accepts MS Ajax styled wrapped and raw JSON objects (as long as a matching  parameter type signature is available) and these two are causing problems in FireFox for the same reason at least in my code.

I've fixed this bug in the West Wind AJAX Toolkit and it's been updated online. Fixed, but this code is running in a ton of apps on my site so it'll take a bit of time to get funnelled into all nooks and crannies.

The last few days I've been hunting down a few other small bugs in my client libraries related to IE 8 and FireFox 3.0 changes. IE 8 is a lot more finicky when using style properties in code and I've had a number of style.property code fail on me where the code used to run fine in IE 7 and all other main browsers. Most of these are minor formatting issues or auto type conversions that used to work. Most of these are very minor and - hust, hust - they're really sloppy code on my part and should have been changed in the first place rather than a problem in IE 8 stricter rendering and interpretation of CSS.  All of this (that I've been able to track down so far) has been fixed.

Posted in AJAX  ASP.NET  HTML  West Wind Ajax Toolkit  

The Voices of Reason


 

Rik Hemsley
March 12, 2008

# re: Firefox 3.0 XmlHttpRequest Default Content-Type change

"it's probably a good idea in general when looking for content types to use .StartsWith() or explicitly strip out the character set with RegEx to pick up the content type only."

Or actually parse the string properly - according to the RFC.

Rick Strahl
March 12, 2008

# re: Firefox 3.0 XmlHttpRequest Default Content-Type change

Er - isn't that what the latter part implied? <g>

Talk about a sucky RFC standard in the first place that mixes multiple values into a single header property. It sure would be advantages to have charset a separate header but that's "standardization" for 'ya...

Rik Hemsley
March 12, 2008

# re: Firefox 3.0 XmlHttpRequest Default Content-Type change

Yes the regex bit did imply you were considering doing it properly :)

I have to deal with multiple values encoded into one datum all day and it's always painful. I've yet to find out what it is which motivates people to do such a thing. Maybe if I keep hitting them, they'll talk...

Donnie Hale
March 12, 2008

# re: Firefox 3.0 XmlHttpRequest Default Content-Type change

If you are going to short-circuit "proper parsing" and go with quick-and-dirty, it would be better to use .Contains than .StartsWith.

Rick Strahl
March 12, 2008

# re: Firefox 3.0 XmlHttpRequest Default Content-Type change

@Donnie, @Rik - Thanks for your comments.

I do believe the standard calls for the content type to be the first entry with the charset tagged on at the end. If doing this right I suppose we'd parse ALL the headers and split any ; breaks into subkeys, but that's REALLY overkill for such a simple operation.

My error here was not THINKING about this possibility of the charset inclusion, not necessarily in the implementation. It's one thing to parse things properly when you expect the value to be split, but another if you don't. Call it operator error <g>...

This is exactly why splitting multiple values into single header key is silly from an RFC point of view, but then again we're talking about RFC conventions which are often less than optimal.

IAC, I suspect there will be more code like the above out there - code that is based on the assumption that the content type is only the content type.

IrishManInUSA
January 30, 2009

# re: Firefox 3.0 XmlHttpRequest Default Content-Type change

I just ran into this issue with a site I am working on, and I am passing my call into a .net page and then returning the data back to the calling js function. This works very well in all versions of FF except for 3.0 and I don't want to rewrite parts of my site to make this work.

This is the code I am using in my call
objHTTP.open(szHttpMethod, szURL, false);
objHTTP.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
objHTTP.setRequestHeader("Content-length", strDataSent.length);
objHTTP.setRequestHeader("Connection", "close");

objHTTP.onreadystatechange = function(){
if (objHTTP.readyState == 4 || objHTTP.readyState == "complete") {
var hidSite = document.getElementById('hidSiteUrl');
var strHttpserver = "";
if (hidSite == null) {
strHttpServer = hidDomain.value;
} else {
strHttpServer = hidSite.value
}
var strXmlReturn = objHTTP.responseText;
strXmlReturn = strXmlReturn.replace("<Response><item>", "");
strXmlReturn = strXmlReturn.replace("</item></Response>", "");
strXmlReturn = strXmlReturn.replace('<?xml version="1.0" ?>', '');

if (strXmlReturn.indexOf('Error') > - 1) {
if (document.getElementById(_strContentPage + 'hidShowInternal').value == 1) {
radalert(strXmlReturn,500,500,'Xml Error');
}
} else {
_strDataMsg = strXmlReturn;
}
}
}
objHTTP.send(strDataSent);
}



function GetXmlHttpObject() {
var objXMLHttp = null;
if (window.XMLHttpRequest) {
objXMLHttp = new XMLHttpRequest();

}
else if (window.ActiveXObject) {
objXMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return objXMLHttp;
}

I have question out on Experts-Exchange on it, but any help on this would be appreciated. Thanks.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024