Search code examples
javascriptajaxxmlhttprequestmsxml

Fall-back support for XMLHTTPRequest


We have a web application that makes use of native XMLHttpRequest() to send data back to our server. One of our larger clients have users that appear to be running IE8 in Win7 (64-bit) and have "Enable native XMLHTTP support" disabled in their browser.

We've implemented the typical scenario of instantiating an ActiveXObject in place of XMLHttpRequest in order to try to support the likes if IE6 (no native XMLHTTP support; yes, we still have clients running this on thin clients!) which I am hoping IE8 can utilise as a fallback if this checkbox option has been switched off. However, once an object has been created, I get a type error when calling open() method on it.

Here's my code:

// Posts back an xml file synchronously and checks for parse error.
// Returns xml object or null.  Used in RSUserData.
XML.PostXmlFile = function(sURL, doc)
{
    try
    {
        // Validate Input
        if ((typeof (sURL) != "string") || (sURL == ""))
            return null;

        if (window.XMLHttpRequest)  // IE7+, FF and Chrome
        {
            // Mozilla, create a new DOMParser and parse from string
            // Although IE9 and IE10 can successfully load XML using this block, it can't use document.evaluate nor selectNodes/selectSingleNode to navigate it
            // Ref: http://msdn.microsoft.com/en-us/library/ie/ms535874(v=vs.85).aspx
            // Ref: http://msdn.microsoft.com/en-us/library/ie/ms534370(v=vs.85).aspx
            // Ref: http://blogs.msdn.com/b/ie/archive/2012/07/19/xmlhttprequest-responsexml-in-ie10-release-preview.aspx
            var req = new XMLHttpRequest();
            req.open("post", sURL, false);
            req.send(doc);
            if (req.status != 200)
                throw { message: 'HTTP Post returned status ' + req.status + ' (' + req.statusText + ') when sending to ' + sURL };

            // IE11+:   req.responseXML returns a native XML Document
            // IE9/10:  req.responseXML returns an IXMLDOMDocument2 object but we can convert req.responseText to native XML using DOMParser
            // IE6/7/8: req.responseXML returns an IXMLDOMDocument2 object but DOMParser is not available

            if (window.DOMParser)
            {
                var parser = new DOMParser();
                return parser.parseFromString(req.responseText, 'application/xml');
            }
            else
                return req.responseXML;     // NATIVE
        }
        else
        {
            // up to IE6:
            // Ref: http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
            var oXML = XML.GetActiveX_XML();
            if (!oXML)
                throw { message: "Could not instantiate an Msxml2 ActiveXObject", innerException: e };

            oXML.open('POST', sURL, true);
            oXML.send(sFile);
            if (oXML.parseError.errorCode == 0)
            {
                xmlDoc = oXML;
                return xmlDoc;
            }
            return null;
        }

    }
    catch (e)
    {
        var s = "Exception in XML.PostXmlFile(). " + (e.message ? e.message : "");
        throw { message: s, innerException: e };
    }
}


XML.GetActiveX_XML = function()
{
    var progIDs = ['Msxml2.DOMDocument.6.0', 'Msxml2.DOMDocument.3.0'];
    for (var i = 0; i < progIDs.length; i++)
    {
        try
        {
            var oXML = new ActiveXObject(progIDs[i]);
            var sl = oXML.getProperty("SelectionLanguage");
            if (sl !== "XPath")
                oXML.setProperty("SelectionLanguage", "XPath"); // Changes v3.0 from XSLPattern to XPath

            var ns = "xmlns:rs='" + XML._nsResolver('rs') + "' xmlns:xsi='" + XML._nsResolver('xsi') + "'";
            //          ns = "xmlns:na='http://myserver.com' xmlns:nb='http://yourserver.com'";
            oXML.setProperty("SelectionNamespaces", ns);
            return oXML;
        }
        catch (ex) { }
    }
    return null;
}

NOTES:

  • The aim is to call to XML.PostXmlFile() with the url and payload.
  • Modern browsers use new XMLHttpRequest() as expected
  • IE6 is expected to use XML.GetActiveX_XML() on account that window.XMLHttpRequest returns falsey
  • IE8 with "Enable native XMLHTTP support" disabled falls through to the IE6 code (because window.XMLHttpRequest returns falsey) but the instantiated object fails because it doesn't support open() method (oXML.open('POST', sURL, true);)

Is there any way I can post my payload back using IE8 when "Enable native XMLHTTP support" is disabled?


Solution

  • You should see if the Microsoft.XMLHTTP is available before checking if there is a XMLHttpRequest:

    var bActiveX;
    
    try {
      new ActiveXObject('Microsoft.XMLHTTP');
      bActiveX = true;
    }
    catch(e) {
      bActiveX = false;
    }
    

    And then, check in your if condition:

    if (window.XMLHttpRequest || bActiveX) { // IE7+, FF and Chrome
      var req = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
    
      /* the rest of your code */
    }