IE9 jQuery AJAX with CORS returns "Access is denied"

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


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

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


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/