64

I am doing a cross domain request using $.ajax. It works on Firefox and Chrome, but does not issue a call on IE 7 or 8. Can anyone tell me what's wrong with the following?

  1. I have used JSON and JSONP (which I stopped using, due to some custom restrictions).
  2. I am already using Allow-access-control-origin header on my site. (Without those, Chrome and Firefox were not making successful requests.)
  3. I have already tried https://developer.mozilla.org/en/http_access_control

Code:

$.ajax({
    type: 'GET',
    url: "http://anotherdomain.com/Service/GetControl?id=" + zoneID,
    cache: false,
    contentType: "application/x-www-form-urlencoded",
    async: false,
    beforeSend: function (request) {
        //alert('before send');
        //request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
        //request.setRequestHeader("X-PINGOTHER", "pingpong");
    } ,
    success: function (data, status) {
        //alert("Data returned :" + data);
        //alert("Status :" + status);
        if (status == "success" && data != "")
            $("#" + div.id).append(data);
        else
            $("#" + div.id).attr("style", "display:none;");
    },
    error: function (XMLHttpRequest, textStatus, errorThrown) {
        alert(textStatus);
        alert(errorThrown);
    }
});

I have tried various tips present on multiple sites, but no luck yet.

Community
  • 1
  • 1
Furqan Hameedi
  • 4,372
  • 3
  • 27
  • 34

14 Answers14

63

For IE8 & IE9 you need to use XDomainRequest (XDR). If you look below you'll see it's in a sort of similar formatting as $.ajax. As far as my research has got me I can't get this cross-domain working in IE6 & 7 (still looking for a work-around for this). XDR first came out in IE8 (it's in IE9 also). So basically first, I test for 6/7 and do no AJAX.

IE10+ is able to do cross-domain normally like all the other browsers (congrats Microsoft... sigh)

After that the else if tests for 'XDomainRequest in window (apparently better than browser sniffing) and does the JSON AJAX request that way, other wise the ELSE does it normally with $.ajax.

Hope this helps!! Took me forever to get this all figured out originally

Information on the XDomainRequest object

// call with your url (with parameters) 
// 2nd param is your callback function (which will be passed the json DATA back)

crossDomainAjax('http://www.somecrossdomaincall.com/?blah=123', function (data) {
    // success logic
});

function crossDomainAjax (url, successCallback) {

    // IE8 & 9 only Cross domain JSON GET request
    if ('XDomainRequest' in window && window.XDomainRequest !== null) {

        var xdr = new XDomainRequest(); // Use Microsoft XDR
        xdr.open('get', url);
        xdr.onload = function () {
            var dom  = new ActiveXObject('Microsoft.XMLDOM'),
                JSON = $.parseJSON(xdr.responseText);

            dom.async = false;

            if (JSON == null || typeof (JSON) == 'undefined') {
                JSON = $.parseJSON(data.firstChild.textContent);
            }

            successCallback(JSON); // internal function
        };

        xdr.onerror = function() {
            _result = false;  
        };

        xdr.send();
    } 

    // IE7 and lower can't do cross domain
    else if (navigator.userAgent.indexOf('MSIE') != -1 &&
             parseInt(navigator.userAgent.match(/MSIE ([\d.]+)/)[1], 10) < 8) {
       return false;
    }    

    // Do normal jQuery AJAX for everything else          
    else {
        $.ajax({
            url: url,
            cache: false,
            dataType: 'json',
            type: 'GET',
            async: false, // must be set to false
            success: function (data, success) {
                successCallback(data);
            }
        });
    }
}
Mark Pieszak - Trilon.io
  • 61,391
  • 14
  • 82
  • 96
  • 2
    If only I could 'mark as favorite' an answer instead of the question :) – Vikram Deshmukh Jul 07 '14 at 12:34
  • 1
    It is working perfectly but What should I do for POST requests in IE8 & IE9 – Surya Jul 19 '14 at 10:35
  • @Surya Look at this example: http://stackoverflow.com/a/12233050/1492009. I made this function a long time ago, since then I've made it much more versatile / passing in what type (get/post). But you just pass it in like normal: `xdr.open('POST', url);` – Mark Pieszak - Trilon.io Jul 23 '14 at 15:24
  • Passing over client authentication will not work with XDomainRequest. (If you are looking for a substitute for xhrFields:{withCredentials:true} ) Neither authentication or cookies will be passed along according to the post below http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx – Dan Feb 04 '15 at 10:58
  • For what it's worth, it seems that "data.firstChild.textContent" is not a feasible value in the error-fallback section of the onload function. I replaced it with "xdr.responseText.firstChild.textContent"... that should produce more consistent results and actually pass linting. – Crates Jan 24 '17 at 19:21
32

Could you check if the problem with IE relies on not defining security zones to allow cross domain requests? See this microsoft page for an explanation.

OTOH, this page mentions that IE7 and eariler cannot do cross domain calls, but IE8 can, using a different object than XMLHttpRequest, the one JQuery uses. Could you check if XDomainRequest works?

EDIT (2013-08-22)

The second link is dead, so I'm writing here some of its information, taken from the wayback machine:

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();
Community
  • 1
  • 1
Luciano
  • 8,552
  • 5
  • 32
  • 56
  • Thanks luciano, I Checked with XDomainRequest and for IE8 it worked, though i have to write seperate script to cater IE8 specially. – Furqan Hameedi Aug 02 '10 at 05:45
  • 1
    yup, doing almost the same , but using $.ajax for all the browsers except for IE8, $.ajax is working on IE6,IE7,FF3.5&Chrome , but for IE8 have written the same XdomainRequest code. – Furqan Hameedi Aug 04 '10 at 10:54
  • 1
    Today I come across another solution to my problem, since in IE 8 the code works just by sending following header Header Name = "p3p", VALUE = "CP=IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT" – Furqan Hameedi Feb 01 '11 at 11:29
  • how about an example. did you add this to the beforeSend function? – Anthony Nov 01 '11 at 15:43
  • @Furqan This does not work. Just tested IE8, Windows 7 -- the problem is jQuery doesn't even begin the transation... – tkone Apr 02 '12 at 15:36
  • IE needs much more hand-holding than other browsers for cors to work. I had the same problem but fixed it with http://forum.jquery.com/topic/cross-domain-ajax-and-ie where there is a block of code you can drop in to fix the issue. – daveagp May 30 '12 at 17:12
  • 2
    @Furqan Setting a P3P header has nothing to do with permitting cross-domain requests. That *response* header concerns whether a given cookie will be set or blocked as a privacy risk. – EricLaw Mar 15 '13 at 19:17
  • The second link (actionmonitor.co.uk) is dead. – ashack Aug 22 '13 at 19:29
23

Jquery does this for you, only thing is to set $.support.cors = true; Then cross domain request works fine in all browsers for jquery users.

Tisho
  • 8,320
  • 6
  • 44
  • 52
Anand
  • 438
  • 3
  • 5
  • 6
    if you look at the date when this question was asked, at that time jquery did not used to support that attribute, it was introduced later on and still it does not accomplishes the scenario by just setting it to true, there are server side settings that you need to tweak with as well. – Furqan Hameedi Jul 17 '12 at 10:06
  • what are the server headers that need to be sent? – Michael Yagudaev Jan 04 '13 at 23:09
  • 12
    $.support.cors = true; - do not seem to work in IE8 even with the latest jquery till date. – Tito Mar 21 '13 at 13:21
  • 11
    This is not true for IE 8 or 9. You still need to use XDomainRequest. Simply setting $.support.cors = true is not enough. – d512 Sep 23 '13 at 16:13
  • 1
    Does not have an impact in IE8, jQuery 1.10.2 :( – Ain Tohvri Jan 14 '14 at 15:25
  • This solution works for me using jQuery 1.11.0 in IE9 set to IE8 standards mode. – Greg Prisament Jun 02 '15 at 23:59
20

Simply install this jQuery Plugin: jQuery Cross-Domain AJAX for IE8

This 1.4kb plugin works right away in Internet Explorer 8 and 9.

Include the plugin after jQuery, and call your ajax request as normal. Nothing else required.

Bradley Flood
  • 10,233
  • 3
  • 46
  • 43
  • Thanks dear for your helping hand.Your answer might help someone facing the same issue. – Furqan Hameedi Sep 26 '13 at 09:24
  • 5
    Worked for me in IE7-9 on jQuery 1.8.3. This plugin is exceedingly difficult to find. If anyone stumbles across this, please give this answer the upvotes it deserves. – Anthony DiSanti Jun 06 '14 at 05:42
  • Just a note: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest does not allow cross protocol calls. – Jason D. Oct 08 '15 at 15:58
7

Add extra transport to jquery for IE. ( Just add this code in your script at the end )

$.ajaxTransport("+*", function( options, originalOptions, jqXHR ) {

    if(jQuery.browser.msie && window.XDomainRequest) {

        var xdr;

        return {

            send: function( headers, completeCallback ) {

                // Use Microsoft XDR
                xdr = new XDomainRequest();

                xdr.open("get", options.url);

                xdr.onload = function() {

                    if(this.contentType.match(/\/xml/)){

                        var dom = new ActiveXObject("Microsoft.XMLDOM");
                        dom.async = false;
                        dom.loadXML(this.responseText);
                        completeCallback(200, "success", [dom]);

                    }else{

                        completeCallback(200, "success", [this.responseText]);

                    }

                };

                xdr.ontimeout = function(){
                    completeCallback(408, "error", ["The request timed out."]);
                };

                xdr.onerror = function(){
                    completeCallback(404, "error", ["The requested resource could not be found."]);
                };

                xdr.send();
          },
          abort: function() {
              if(xdr)xdr.abort();
          }
        };
      }
    });

This solved my problem with Jquery $.ajax failing for Cross Domain AJAX request.

Cheers.

Jay Dave
  • 1,773
  • 1
  • 13
  • 9
  • When this question was asked in 2010, jquery was not mature enough, your solution might have solved the problem but its a little late now.Thanks for the helping hand anyways. – Furqan Hameedi Aug 24 '12 at 10:47
5

Others coming around here might do well to read http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx which talks about limitations of XDomainRequest

Ayush Gupta
  • 5,568
  • 2
  • 21
  • 17
3

For anyone whom might still have this problem using jQuery 2.0 (I know I do), Jay Dave wrote the best jQuery workaround but I still have a few things to add to his code namely:

  • make sure you are using the same protocol for requests (HTTP -> HTTP or HTTPS -> HTTPS), Ayush Gupta gave a link to knows issues
  • handle the "onprogress" events with a no-op function (this will prevent IE from abording the requests after it receives the first bits from the server.

The complete code is below:

// add ajax transport method for cross domain requests when using IE9
if('XDomainRequest' in window && window.XDomainRequest !== null) {
   $.ajaxTransport("+*", function( options, originalOptions, jqXHR ) {
       // verify if we need to do a cross domain request
       // if not return so we don't break same domain requests
       if (typeof options.crossDomain === 'undefined' || !options.crossDomain) {
           return;
       }

        var xdr;

        return {
            send: function( headers, completeCallback ) {
                // Use Microsoft XDR
                xdr = new XDomainRequest();
                xdr.open("get", options.url); // NOTE: make sure protocols are the same otherwise this will fail silently
                xdr.onload = function() {
                    if(this.contentType.match(/\/xml/)){
                        var dom = new ActiveXObject("Microsoft.XMLDOM");
                        dom.async = false;
                        dom.loadXML(this.responseText);
                        completeCallback(200, "success", [dom]);
                    } else {
                        completeCallback(200, "success", [this.responseText]);
                    }
                };

                xdr.onprogress = function() {};

                xdr.ontimeout = function(){
                    completeCallback(408, "error", ["The request timed out."]);
                };

                xdr.onerror = function(){
                    completeCallback(404, "error", ["The requested resource could not be found."]);
                };

                xdr.send();
            },
            abort: function() {
                if(xdr) xdr.abort();
            }
        };
    });
}
alecs.popa
  • 145
  • 1
  • 5
  • Doesn't work for me on jQuery 1.11.1, but due to IE: no reasonable error message :'-( The original plugin does work, though: https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js – Simon Steinberger Nov 28 '14 at 17:57
2

Simply add "?callback=?" (or "&callback=?") to your url:

$.getJSON({
    url:myUrl + "?callback=?",
    data: myData,
    success: function(data){
        /*My function stuff*/        
    }
});

When doing the calls (with everything else set properly for cross-domain, as above) this will trigger the proper JSONP formatting.

More in-depth explanation can be found in the answer here.

Community
  • 1
  • 1
Randy Hall
  • 7,716
  • 16
  • 73
  • 151
  • 1
    @Furqan Just putting it out there for anyone who comes across this problem (like myself, recently). – Randy Hall Mar 16 '13 at 13:00
  • Works for me... on one of the busiest retail sites on the planet. Do you have a fiddle or something we can see? – Randy Hall Nov 20 '13 at 16:08
  • 1
    You've misunderstood the problem. This issue revolves around IE8's support for Cross-Domain AJAX calls, which can only be solved by referring to solutions involving CORS and XDomainRequest (a la https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest which solved the prolem for me). If the problem could be solved by just sticking an extra argument on the QueryString, don't you think your answer would be the accepted one? And don't you think it would be a rather large security hole if that really was the answer? – James McCormack Nov 22 '13 at 15:29
  • Better? Didn't expect to see this come up 8 months later... some people apparently found it useful enough to up-vote. – Randy Hall Nov 22 '13 at 16:11
  • @JamesMcCormack added a link to another answer. Trying to overcome the issue, I found that answer to work, but it was well hidden. I put the answer here so others with the same problem, who searched for the same thing, would find this information. – Randy Hall Nov 22 '13 at 16:17
2

Note, adding

$.support.cors = true;

was sufficient to force $.ajax calls to work on IE8

jpantona
  • 154
  • 2
  • 9
  • thanks for your helping bit. Your answer may help other people searching, for me it is too late to serve, as at the time of question, jquery did not have that support for IE8. – Furqan Hameedi Nov 19 '13 at 07:50
  • Already have this property set to true, and it still doesn't work in IE8. – SikoSoft Dec 12 '17 at 12:35
1

@Furqan Could you please let me know whether you tested this with HTTP POST method,

Since I am also working on the same kind of situation, but I am not able to POST the data to different domain.

But after reading this it was quite simple...only thing is you have to forget about OLD browsers. I am giving code to send with POST method from same above URL for quick reference

function createCORSRequest(method, url){
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr){
    xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined"){
    xhr = new XDomainRequest();
    xhr.open(method, url);
} else {
    xhr = null;
}
return xhr;
}

var request = createCORSRequest("POST", "http://www.sanshark.com/");
var content = "name=sandesh&lastname=daddi";
if (request){
    request.onload = function(){
    //do something with request.responseText
   alert(request.responseText);
};

 request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            request.setRequestHeader("Content-length", content.length);
            request.send(content);
}
Flexo
  • 87,323
  • 22
  • 191
  • 272
0

I have the same problem in IE, I solved it by replacing:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>

To

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

So basically upgrade your jquery version.

KingBowen
  • 240
  • 3
  • 9
0

I had a similar problem in IE9 where some CORS calls were aborting, while others weren't. My app is also dependent on a promise interface, so the XDomainRequest suggestions above weren't EXACTLY what I needed, so I added a deferred into my service.get workaround for IE9. Hopefully it can be useful to someone else running across this problem. :

    get: function (url) {
        if ('XDomainRequest' in window && window.XDomainRequest !== null) {
            var deferred = $.Deferred();
            var xdr      = new XDomainRequest();

            xdr.open("get", url);

            xdr.onload = function() {
              json = xdr.responseText;
              parsed_json = $.parseJSON(json);
              deferred.resolve(parsed_json);
            }

            xdr.send();
            return deferred;
        } else {
            return $.ajax({
                url: url,
                type: 'GET',
                dataType: 'json',
                crossDomain: true
            });
        }
    }
David Savage
  • 1,562
  • 2
  • 18
  • 35
0

Microsoft always ploughs a self-defeating (at least in IE) furrow:

http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/

CORS works with XDomainRequest in IE8. But IE 8 does not support Preflighted or Credentialed Requests while Firefox 3.5+, Safari 4+, and Chrome all support such requests.

Raman
  • 1
  • 1
-1

It's hard to tell due to the lack of formatting in the question, but I think I see two issues with the ajax call.

1) the application/x-www-form-urlencoded for contentType should be in quotes

2) There should be a comma separating the contentType and async parameters.

KallDrexx
  • 27,229
  • 33
  • 143
  • 254
  • Hi Kall , thanks for your response. I tried your suggestion too , in question it was mistyped. Its working fine in Chrome and Firefox , for preflighted requests but not working in IE. Yet unable to tell why? please do share me any more tips if you have. – Furqan Hameedi Aug 01 '10 at 06:12