Microsoft's XMLHttpRequest ActiveX Objects

This is an excerpt from my book, Accelerated DOM Scripting available at Amazon and other fine retailers. Although it's only a small section of the book, it's one of my favourite pieces because it had always been a mystery to me.

If you’ve scoured through any number of Ajax solutions, you might have noticed different XMLHttpRequest objects being referred to. Microsoft’s XML implementation is known as MSXML and comes in many versions.

Here’s the list:

  • Microsoft.XMLHTTP
  • Msxml2.XMLHTTP
  • Msxml2.XMLHTTP.3.0
  • Msxml2.XMLHTTP.4.0
  • Msxml2.XMLHTTP.5.0
  • Msxml2.XMLHTTP.6.0

An article from the Microsoft XML team explains in some detail the differences between what the different versions are and how they should be used (but it’s still not entirely clear).

MSXML 1.0 and 2.0 are no longer supported by Microsoft. Version 4.0 never saw an operating system release, and version 5.0 was a special version for Microsoft Office. The version-independent IDs, Microsoft.XMLHTTP and Msxml2.XMLHTTP, now map directly to version 3.0 (even if version 6.0 is installed). This really only leaves you with two possible program IDs (referred to as progIDs by Microsoft):

  • Msxml2.XMLHTTP
  • Msxml2.XMLHTTP.6.0

Version 6 was introduced in IE 7 and includes some bug fixes such as the one where IE 5 and 6 fail when the onreadystatechange is declared before the open call. Although IE 7 includes a native XHR object, users have the option of disabling it. Therefore, it’s a good idea to test for Msxml2.XMLHTTP.6.0 first; if it doesn’t work, fall back to the other version.

Here's a quick example checking for the native object before checking for the IE-specific versions:

/**
   Will return a valid object if successful
*/
function XHR()
{
  var transport;
  // check native support first
  if(window.XMLHttpRequest) {
    transport = new XMLHttpRequest();
  }else{
    // check for version 6 before version 3
    try{ transport = new ActiveXObject("MSXML2.XMLHTTP.6.0");  }catch(e){}
    try{ if(!transport) transport = new ActiveXObject("MSXML2.XMLHTTP");  }catch(e){}
  }
  return transport;
}
Published January 21, 2008
Categorized as JavaScript
Short URL: https://snook.ca/s/865

Conversation

12 Comments · RSS feed
Robert Nyman said on January 21, 2008

It's good to have these listed. and to understand what they really are!
Nitpicking, just one small thing: given Douglas Crockford's and others' advice, do you really want the starting { on a separate line?

Short example: JavaScript Style - why it’s important

Jonathan Snook said on January 21, 2008

Yes, I still prefer putting the { on a new line. I find it easier for seeing where my functions start and end. For returns, I don't like returning an object literal, so I'll always assign it to a variable and then return the variable. I find the code more readable that way and, as it turns out, avoids the issue described.

Chris A said on January 21, 2008

try{ transport = new ActiveXObject("MSXML2.XMLHTTP.6.0");  }catch(e){}
try{ transport = new ActiveXObject("MSXML2.XMLHTTP");  }catch(e){}

Shouldn't the order of those lines be reversed? That way IE7 users with the XHR object disabled will get the 6.0 instead of the 3.0. Or am I not following? It seems to me that, in IE7 with XHR disabled, the first statement will succeed and the transport variable will reference the 6.0 version. And then the second statement will also succeed and the transport variable will now reference the 3.0 version.

Jonathan Snook said on January 21, 2008

@Chris A: Good catch. I've updated the code example in the article with an IF check in the second TRY statement. (Now to put together my first errata for the book...)

Chris Lienert said on January 21, 2008

I usually return the object as soon as possible i.e.

try {
  return new ActiveXObject("Msxml2.XMLHTTP.6.0");
} catch(e) {
  try {
    return new ActiveXObject("Msxml2.XMLHTTP");
  } catch(e) {
    return null;
  }
}

Robert Nyman said on January 22, 2008

Yes, that solves that specific issue. But to me, at least, it seems like sound advice to always have it on the same line as the code, to avoid any potential hazards with semi-colons inserted automatically by the interpretor.

Terry Apodaca said on January 22, 2008

Very nice!

Greg Ferrell said on January 23, 2008

Robert,

There are no known issues with having your beginning bracket on a new line and accidental semi-colon insertion when dealing with functions, for/while-loops, if/then statements, etc in JavaScript. Even Crockford does some of his code this way.

The issue comes into focus when you are dealing with objects.

Greg Ferrell said on January 23, 2008

I should correct my last statement above to say:

The issue comes into focus when you are dealing with literals.

Breaking after a parenthesis is perfectly fine.

Dan said on January 24, 2008

Being an ECMAScript Engine author, I shall call you on that.

Semicolons are technically *required* after break, continue, return and throw statements, and newline is now allowed between break and any following identifier token. Any engine which assumes a newline after a break is a semicolon is violating standard.

When I code in it, I always explicitly write it;

I might also mention that:

if(window.XMLHttpRequest)
return new XMLHttpRequest();
else if(window.ActiveXObject)
return new ActiveXObject("msxml2.xmlhttp");
else
throw new Error("Could not find XMLHttpRequest Object");

works fine, provided you remember to put open before onreadystatechange.

Regards,
Dan

17yad18izx said on January 19, 2009

Hi! Ebanij vrot! tb7oh8ki77 vn254iax6g!

lolkitradioto said on March 06, 2011

ceea ce I was privire pentru, multumesc

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.

Want to learn about scaling CSS for large projects?

I'm available for full and half-day workshops on scalable CSS architecture. I can provide on-site training for your team. Interested?
Get in touch.