Blog Posting

Javascript data access techniques (XMLHttpRequest vs XDomainRequest vs IFrame Form vs Javascript SRC) - 21/02/2010

This post is here to compare and contrast different ways of sending data to a server resource on either a local or remote server in Javascript. The following techniques are the most widely supported;

  • XMLHttpRequest (Single Domain only client method)
  • CORS XMLHttpRequest (Cross-Domain with 'Access-Control-Allow-Origin' header)
  • XDomainRequest
  • IFrame Form technique
  • Javascript SRC technique

They aren't all available in every browser, or usefull for every situation, so this post is intended to discuss the benefits and disadvantages of each.

XMLHttpRequest (Single Domain only client method)

Supported: IE5+ (IE5/5.5/6 support via ActiveX), Firefox (all versions), Chrome all versions, Safari 1.2+, Opera 7.6+

When making requests for resources on the same domain XmlHttpRequest is usually the best option. Supported by all the major browsers in use today. Difference in implementation in IE versions prior to 7 (where it wasnt a native object), makes it slightly long winded to use.

var xmlhttp;

try {
	xmlhttp = new XMLHttpRequest();
}
catch (e) {
	try {
		xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
	}
	catch (ex) {
		xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
	}
}


xmlhttp.open('GET', "script.html", true);

xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { alert("READY"); } };
xmlhttp.send();

To make this work in a cross domain fashion, a server side script needs to run as a type of proxy. This proxy script can simply fetch a file from another domain, which bypasses the same-origin problem on the client side). Here is an example of how this could be done in ASP.NET (from Rick Strahl's site at west-wind.com);

string lcUrl = "http://www.example.org";
 
// *** Establish the request
HttpWebRequest loHttp = (HttpWebRequest) WebRequest.Create(lcUrl);
 
// *** Set properties
loHttp.Timeout = 10000;     // 10 secs
loHttp.UserAgent = "Code Sample Web Client";
 
// *** Retrieve request info headers
HttpWebResponse loWebResponse = (HttpWebResponse) loHttp.GetResponse();
 
Encoding enc = Encoding.GetEncoding(1252);  // Windows default Code Page
 
StreamReader loResponseStream =
   new StreamReader(loWebResponse.GetResponseStream(),enc);
 
string lcHtml = loResponseStream.ReadToEnd();
 
loWebResponse.Close();
loResponseStream.Close();

This method, of course places extra burden in terms of bandwith on the server, and can be slower overall due to extra steps in making the request.

CORS XMLHttpRequest (Cross-Domain with 'Access-Control-Allow-Origin' header)

Supported: Firefox 3.5+, Safari 4+, Chrome 2+

For the browsers that support it (which can be detected via the presence of the 'withCredentials' property), the new CORS (Cross Origin Sharing) version of XmlHttpRequest is highly usefull and easy tow ork with. On the client side, the code is fundamently the same as with the single-domain XmlHttpRequest object. Unfortunately, this technology isn't prevelant enough to be relied upon just yet.

var xmlhttp = new XMLHttpRequest();

xmlhttp.open('GET', "script.html", true);
xmlhttp.withCredentials = true;

xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { alert("READY"); } };
xmlhttp.send();

With this technique, the server needs to respond with a certain header. Here is an example of how you could set this header (with a wildcard, so that all domains can access the content) in ASP.NET;

Response.AddHeader("Access-Control-Allow-Origin", "*");
XDomainRequest

Supported: IE8

Rather than implement the CORS version of XMLHttpRequest, the IE team have gone with there own propriety object, named XDomainRequest. The usage of XDomainRequest has been simplified from XMLHttpRequest, by having more events thrown (with onload perhaps being the most important).

This implementation has a few limitations attached to it. For example, cookies are not sent when using this object, which can be a headache for cookie based sessions on the server side. Also, ContentType can not be set, which poses a problem in ASP.NET and possibly other server side languages (see http://www.actionmonitor.co.uk/NewsItem.aspx?id=5).

var xdr = new XDomainRequest();

xdr.onload = function() { alert("READY"); };

xdr.open("GET", "script.html");
xdr.send();
}

Much the same as when using the CORS XMLHttpRequest, with this technique, the server needs to respond with a certain header. Here is an example of how you could set this header (with a wildcard, so that all domains can access the content) in ASP.NET;

Response.AddHeader("Access-Control-Allow-Origin", "*");
IFrame Form technique

Supported: IE 3+, Opera 3+, All other major PC browsers since 1997

One method that is usefull for sending large amounts of data to a remote web site (but you don't need to read the data returned), is to use a hidden IFrame on your page to POST the remote site. The downside to this technique is that it adds an entry to your browsers history, which can break the back/forward functionality.

Many code samples can be found online to do this so I havn't gave an example here (plus it is pretty long winded)

Javascript SRC technique

Supported: Any browser that supports Javascript

If you are need some data back from a remote web site, and you don't need to send much data to the site, the Javascript SRC method can be of use. Disadvantages of this method is that you can only send up as much data as the querystring permits (about 3000 characters to be safe accross different browsers).

var params = "param1key=param1value¶m2key;=param2value";

var html_doc = document.getElementsByTagName('head').item(0);
var js = document.createElement('script');

js.setAttribute('language', 'javascript');
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', 'script.html?' + params);

html_doc.appendChild(js);
Resources

http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
http://www.west-wind.com/presentations/dotnetWebRequest/dotnetWebRequest.htm

Comments

No comments to display!

Post A Comment