By Garrett


2012-04-19 15:56:27 8 Comments

The following works in all browsers except IE (I'm testing in IE 9).

jQuery.support.cors = true;
...
        $.ajax(
            url + "messages/postMessageReadByPersonEmail",
            {
                crossDomain: true,
                data: {
                    messageId       : messageId,
                    personEmail     : personEmail
                },
                success: function() {
                    alert('marked as read');
                },
                error: function(a,b,c) {
                    alert('failed');
                },
                type: 'post'
            }
        );

I have another function which uses dataType: 'jsonp', but I don't need any data returned on this AJAX call. My last resort will be to return some jibberish wrapped in JSONP just to make it work.

Any ideas why IE is screwing up with a CORS request that returns no data?

12 comments

@dennisg 2012-04-19 16:14:42

This is a known bug with jQuery. The jQuery team has "no plans to support this in core and is better suited as a plugin." (See this comment). IE does not use the XMLHttpRequest, but an alternative object named XDomainRequest.

There is a plugin available to support this in jQuery, which can be found here: https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js

EDIT The function $.ajaxTransport registers a transporter factory. A transporter is used internally by $.ajax to perform requests. Therefore, I assume you should be able to call $.ajax as usual. Information on transporters and extending $.ajax can be found here.

Also, a perhaps better version of this plugin can be found here.

Two other notes:

  1. The object XDomainRequest was introduced from IE8 and will not work in versions below.
  2. From IE10 CORS will be supported using a normal XMLHttpRequest.

Edit 2: http to https problem

Requests must be targeted to the same scheme as the hosting page

This restriction means that if your AJAX page is at http://example.com, then your target URL must also begin with HTTP. Similarly, if your AJAX page is at https://example.com, then your target URL must also begin with HTTPS.

Source: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

@Garrett 2012-04-19 18:14:53

Thanks! Any idea how to use that plugin?

@dennisg 2012-04-19 20:19:51

I am not entirely sure, but I've added my assumptions to my answer.

@Kato 2012-06-12 21:47:40

The "better version" of the plugin is innate; I just included it in my page and it automagically fixed my $.ajax calls :) Assuming, of course, that you have all the necessary headers in place.

@Ziggy 2013-01-16 03:05:00

I am missing something: neither of these are working for me. Include the script via a script tag, then just make ajax calls as normal?

@Ziggy 2013-01-16 03:37:02

If I put an alert statement inside the function passed to ajaxTransport, that statement never gets executed. Additionally, the request (which is to 'localhost') doesn't show up in ie9's developer tool's network panel.

@Volodymyr Otryshko 2013-02-06 16:46:28

To add to dennisg answer, xdr.js has a bug - ajaxTransport callback will not be called as is. I had to change it in accordance with stackoverflow.com/questions/12481560/… (added "+*" as a first argument of ajaxTransport call).

@the0ther 2013-05-01 21:52:02

@VolodymyrOtryshko -- Dude let me buy you a beer! Brilliant comment, fixed all my headaches.

@Robusto 2013-06-20 21:16:57

The $.ajaxTransport function you linked on github does absolutely nothing for me. And I really wanted it to. Darn.

@Aaron 2013-06-25 23:56:13

jQuery.XDomainRequest.js makes sure that the current page and remote page are either both http or https. Does this mean that you cannot make a call to an https API from an http page?

@Ted 2013-06-30 06:14:23

Note if you're dealing with an HTML response, the improved jQuery.XDomainRequest.js only deals with json and xml. My get now works by adding xdr.js. Wonderful (had done browser sniffing previously and done a XDocumentRequest which works for ie8 and ie10, but inexplicably, no go for ie9).

@Clintm 2013-08-21 20:56:04

It's worth noting that the code that was linked to on moonscripts github repo is an old version that doesn't work. Be sure to get the latest version at: raw.github.com/MoonScript/jQuery-ajaxTransport-XDomainReques‌​t/…

@Hari Karam Singh 2014-04-23 09:50:03

@Aaron I had problems with IE when I added the bitly API which was using https. Because the page itself was http, IE wouldn't allow it.

@allicarn 2014-05-31 14:31:36

@Aaron, adding on to @HariKaramSingh's comment: changing protocols (http to https), domains (google.com to bing.com), subdomains (mail.google.com to maps.google.com), or protocols (google.com:80 - the default port to google.com:8080) will all trigger a "cross domain" request. Basically everything before the first / in your URL need to be identical.

@Hanna 2014-10-10 21:39:13

The extending ajax link is now dead.

@Frank 2015-01-06 13:57:23

I've been trying to use this solution, but the cookies setted by the server are never being applied (the ASP.NET_SessionId in particular), so each calls is a new session. I'm on the same protocol, different domain (either different port or domain name), I've tried with jQuery 1.11 or 2.1. Did someone have something similar to this and resolved it, or is there no hope?

@Frank 2015-01-06 15:04:59

Actually, it sets the cookies, but each time the server makes a cors request, the server returns a new set of cookies

@Frank 2015-01-06 19:10:23

I found my issue and patched the source. There really was something missing. I will fork and make a pull request later today with more details

@John Washam 2015-05-28 15:30:10

@Frank, at least if you are using XDomainRequest, it does not allow cookies to be sent or received. See this MSDN blog post for more information, specifically the section titled "No authentication or cookies will be sent with the request."

@Stefan 2015-09-22 06:52:06

If I had read the coments, I would have saved myself a lot of time, but I wasted several hours trying to make ajax calls to an https service from an http site. I added it to the answer to avoid other people runnng into the sampe problem.

@Stanislav 2016-01-31 14:15:19

I had a problem with applying this solution because in my ajax call contained an option 'async: false', while in xdr.js there is an if condition that applies the fix only if async us true.

@Gordon Freeman 2015-10-06 17:21:03

Try to use jquery-transport-xdr jQuery plugin for CORS requests in IE8/9.

@ali bagheri 2015-06-28 21:03:49

Note -- Note

do not use "http://www.domain.xxx" or "http://localhost/" or "IP >> 127.0.0.1" for URL in ajax. only use path(directory) and page name without address.

false state:

var AJAXobj = createAjax();
AJAXobj.onreadystatechange = handlesAJAXcheck;
AJAXobj.open('POST', 'http://www.example.com/dir/getSecurityCode.php', true);
AJAXobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
AJAXobj.send(pack);

true state:

var AJAXobj = createAjax();
AJAXobj.onreadystatechange = handlesAJAXcheck;
AJAXobj.open('POST', 'dir/getSecurityCode.php', true);   // <<--- note
AJAXobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
AJAXobj.send(pack);

@Alkaline 2015-02-13 04:42:48

Update as of early 2015. xDomain is a widely used library to supports CORS on IE9 with limited extra coding.

https://github.com/jpillora/xdomain

@yanni 2014-08-15 22:54:13

Building on the solution by MoonScript, you could try this instead:

https://github.com/intuit/xhr-xdr-adapter/blob/master/src/xhr-xdr-adapter.js

The benefit is that since it's a lower level solution, it will enable CORS (to the extent possible) on IE 8/9 with other frameworks, not just with jQuery. I've had success using it with AngularJS, as well as jQuery 1.x and 2.x.

@jgauffin 2014-04-24 11:07:23

The problem is that IE9 and below do not support CORS. XDomainRequest do only support GET/POST and the text/plain conten-type as described here: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

So if you want to use all HTTP verbs and/or json etc you have to use another solution. I've written a proxy which will gracefully downgrade to proxying if IE9 or less is used. You do not have to change your code at all if you are using ASP.NET.

The solution is in two parts. The first one is a jquery script which hooks into the jQuery ajax processing. It will automatically call the webserver if an crossDomain request is made and the browser is IE:

$.ajaxPrefilter(function (options, originalOptions, jqXhr) {
    if (!window.CorsProxyUrl) {
        window.CorsProxyUrl = '/corsproxy/';
    }
    // only proxy those requests
    // that are marked as crossDomain requests.
    if (!options.crossDomain) {
        return;
    }

    if (getIeVersion() && getIeVersion() < 10) {
        var url = options.url;
        options.beforeSend = function (request) {
            request.setRequestHeader("X-CorsProxy-Url", url);
        };
        options.url = window.CorsProxyUrl;
        options.crossDomain = false;
    }
});

In your web server you have to receive the request, get the value from the X-CorsProxy-Url http header and do a HTTP request and finally return the result.

My blog post: http://blog.gauffin.org/2014/04/how-to-use-cors-requests-in-internet-explorer-9-and-below/

@jwill212 2013-11-07 13:37:15

I was testing a CORS web service on my dev machine and was getting the "Access is denied" error message in only IE. Firefox and Chrome worked fine. It turns out this was caused by my use of localhost in the ajax call! So my browser URL was something like:

http://my_computer.my_domain.local/CORS_Service/test.html

and my ajax call inside of test.html was something like:

//fails in IE 
$.ajax({
  url: "http://localhost/CORS_Service/api/Controller",
  ...
});

Everything worked once I changed the ajax call to use my computer IP instead of localhost.

//Works in IE
$.ajax({
  url: "http://192.168.0.1/CORS_Service/api/Controller",
  ...
});

The IE dev tools window "Network" tab also shows CORS Preflight OPTIONS request followed by the XMLHttpRequest GET, which is exactly what I expected to see.

@MoonScript 2013-06-17 18:01:42

Complete instructions on how to do this using the "jQuery-ajaxTransport-XDomainRequest" plugin can be found here: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest#instructions

This plugin is actively supported, and handles HTML, JSON and XML. The file is also hosted on CDNJS, so you can directly drop the script into your page with no additional setup: http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest.min.js

@Cymen 2014-05-09 22:41:59

This worked great -- drop in fix. Unbelievable that this issue exists in jQuery but... Thank you!

@hacklover 2013-07-08 08:04:25

To solve this problem, also check if you have some included .js into your ajax file called: I received Access denied error while including shadowbox.js in my ajax.php

@JackMorrissey 2013-01-22 17:01:55

Building off the accepted answer by @dennisg, I accomplished this successfully using jQuery.XDomainRequest.js by MoonScript.

The following code worked correctly in Chrome, Firefox and IE10, but failed in IE9. I simply included the script and it now automagically works in IE9. (And probably 8, but I haven't tested it.)

var displayTweets = function () {
    $.ajax({
        cache: false,
        type: 'GET',
        crossDomain: true,
        url: Site.config().apiRoot + '/Api/GetTwitterFeed',
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        success: function (data) {
            for (var tweet in data) {
                displayTweet(data[tweet]);
            }
        }
    });
};

@James Ford 2013-01-28 12:52:04

The jQuery.XDomainRequest.js plugin was exactly what I needed! I couldn't get the iexhr.js plugin to work for requests behind HTTP Basic Authentication, but XDomainRequest worked like a charm!

@Nicholas Decker 2013-03-15 20:48:43

This worked for me. I didn't need Site.config().apiRoot + (which I'm assuming is for twitter....) But it works great, thanks for doing this.

@JackMorrissey 2013-03-15 21:41:52

@NicholasDecker Site.config().apiRoot was just implementation specific code to get the root URL of the API, nothing universal or fancy. Glad it helped!

@Jack Marchetti 2013-04-18 20:06:00

I was hoping this would work for me, but I'm trying to POST. wonder if that's the problem for me.

@Jez D 2013-07-30 15:19:40

Same problem, resolved the same way. Thanks @Moonscript

@Fernando Vezzali 2013-08-22 10:47:09

Hey @JackMarchetti, for POST requests it doesn't work for me.

@zanona 2014-01-15 20:18:54

thanks @SwampDiner, it works fine, it's a shame POST requests are sent as text/plain but it did the trick for me.

@cracker 2014-06-16 06:16:39

I am having the same problem and i also refered the above links and put the jquery.xdomainrequest.min.js script in my current page but on post event it goes to jquery.min.js and result to No Access-Control-Allow-Origin header is present on the requested resource. what i need to do in this case?

@JackMorrissey 2014-06-16 15:39:58

@cracker Are you only having issues with POST? Double check the script is loading after jQuery and your call matches MoonScript's documentation.

@cracker 2014-06-18 06:15:55

it's going into jquery.min.js only but anyways thanks for the reply as i have added the Headers from back end and it's working fine now..

@Joshua Dance 2014-11-10 22:50:33

This worked perfect. Dropped the script in, our call pd.$.get(pd.URL, function(data) { //do work with data } works perfectly. Thanks.

@jmarcosSF 2013-05-30 20:11:59

Getting a cross-domain JSON with jQuery in Internet Explorer 8 and newer versions

Very useful link:

http://graphicmaniacs.com/note/getting-a-cross-domain-json-with-jquery-in-internet-explorer-8-and-later/

Can help with the trouble of returning json from a X Domain Request.

Hope this helps somebody.

@Garrett 2012-04-20 17:57:17

I just made all requests JSONP because it was the only solution for all of our supported browsers (IE7+ and the regulars). Mind you, your answer technically works for IE9 so you have the correct answer.

@contactmatt 2013-05-15 03:25:03

But jsonp won't work with a POST...

@mikermcneil 2013-05-25 17:41:38

Just a note to anyone with this problem-- in this case, if you have a <= IE7 requirement, and you don't have control over the server (e.g. can't make it support GET + script tags w/ JSONP) your best bet is a lightweight middleware server which translates the JSONP call to a POST and streams the response from the black box server back to the user.

Related Questions

Sponsored Content

10 Answered Questions

[SOLVED] How to send FormData objects with Ajax-requests in jQuery?

15 Answered Questions

[SOLVED] jQuery AJAX submit form

18 Answered Questions

[SOLVED] Abort Ajax requests using jQuery

31 Answered Questions

[SOLVED] How to manage a redirect request after a jQuery Ajax call

14 Answered Questions

[SOLVED] jQuery AJAX cross domain

0 Answered Questions

8 Answered Questions

[SOLVED] Loading cross-domain endpoint with jQuery AJAX

0 Answered Questions

Why jQuery Ajax or Get not working?

3 Answered Questions

[SOLVED] Cross-domain AJAX requests with IE9

2 Answered Questions

[SOLVED] Cross-domain scripting using jQuery.support.cors = true

Sponsored Content