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.

1

14 Answers 14

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);
            }
        });
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

If only I could 'mark as favorite' an answer instead of the question :)
It is working perfectly but What should I do for POST requests in IE8 & IE9
@Surya Look at this example: 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);
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 blogs.msdn.com/b/ieinternals/archive/2010/05/13/…
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.
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();

8 Comments

Thanks luciano, I Checked with XDomainRequest and for IE8 it worked, though i have to write seperate script to cater IE8 specially.
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.
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"
how about an example. did you add this to the beforeSend function?
@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.
|
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.

6 Comments

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.
what are the server headers that need to be sent?
$.support.cors = true; - do not seem to work in IE8 even with the latest jquery till date.
This is not true for IE 8 or 9. You still need to use XDomainRequest. Simply setting $.support.cors = true is not enough.
Does not have an impact in IE8, jQuery 1.10.2 :(
|
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.

3 Comments

Thanks dear for your helping hand.Your answer might help someone facing the same issue.
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.
Just a note: github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest does not allow cross protocol calls.
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.

1 Comment

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.
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

Comments

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();
            }
        };
    });
}

1 Comment

Doesn't work for me on jQuery 1.11.1, but due to IE: no reasonable error message :'-( The original plugin does work, though: github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js
2

Note, adding

$.support.cors = true;

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

2 Comments

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.
Already have this property set to true, and it still doesn't work in IE8.
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.

5 Comments

@Furqan Just putting it out there for anyone who comes across this problem (like myself, recently).
Works for me... on one of the busiest retail sites on the planet. Do you have a fiddle or something we can see?
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 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?
Better? Didn't expect to see this come up 8 months later... some people apparently found it useful enough to up-vote.
@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.
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);
}

1 Comment

The problem here was old browsers, not the post request.Thanks anywayz for your help.
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.

Comments

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.

Comments

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
            });
        }
    }

Comments

-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.

1 Comment

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.