Jquery $.ajax не работает в IE при междоменных вызовах

Я делаю междоменный запрос, используя $.ajax, Он работает на Firefox и Chrome, но не вызывает вызов на IE 7 или 8. Может кто-нибудь сказать мне, что не так со следующим?

  1. Я использовал JSON и JSONP (которые я перестал использовать из-за некоторых пользовательских ограничений).
  2. Я уже использую Allow-access-control-origin Заголовок на моем сайте. (Без них Chrome и Firefox не делали успешных запросов.)
  3. Я уже пробовал https://developer.mozilla.org/en/http_access_control

Код:

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

Я пробовал различные советы, представленные на нескольких сайтах, но пока не повезло.

14 ответов

Решение

Не могли бы вы проверить, не связана ли проблема с IE с тем, что зоны безопасности не разрешаются для междоменных запросов? Смотрите эту страницу Microsoft для объяснения.

OTOH, на этой странице упоминается, что IE7 и ранее не могут выполнять междоменные вызовы, но IE8 может, используя объект, отличный от XMLHttpRequest, тот, который использует JQuery. Не могли бы вы проверить, работает ли XDomainRequest?

РЕДАКТИРОВАТЬ (2013-08-22)

Вторая ссылка мертва, поэтому я пишу здесь некоторую информацию, взятую с машины обратного хода:

Поддерживается XDomainRequest: IE8

Вместо того чтобы реализовывать версию XMLHttpRequest для CORS, команда разработчиков IE создала собственный объект, называемый XDomainRequest. Использование XDomainRequest было упрощено по сравнению с XMLHttpRequest, благодаря добавлению большего количества событий (при этом, пожалуй, наиболее важной является onload).

Эта реализация имеет несколько ограничений. Например, файлы cookie не отправляются при использовании этого объекта, что может быть головной болью для сеансов на основе файлов cookie на стороне сервера. Кроме того, ContentType не может быть установлен, что создает проблему в ASP.NET и, возможно, на других языках на стороне сервера (см. 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();

Для IE8 и IE9 вам нужно использовать XDomainRequest (XDR). Если вы посмотрите ниже, вы увидите, что он в некотором роде похож на $.ajax. Поскольку мое исследование помогло мне, я не могу заставить этот междоменный домен работать в IE6 и 7 (все еще в поисках обходного пути для этого). XDR впервые появился в IE8 (он тоже в IE9). Итак, сначала я проверяю 6/7 и не делаю AJAX.

IE10 + умеет делать кросс-домены нормально, как и все другие браузеры (поздравляю Microsoft... вздох)

После этого else if проверяет XDomainRequest в окне (по-видимому, лучше, чем анализ браузера) и выполняет JSON AJAX-запрос таким образом, в противном случае ELSE обычно делает это с $.ajax.

Надеюсь это поможет!! Взял меня навсегда, чтобы понять все это изначально

Информация об объекте XDomainRequest

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

Jquery делает это для вас, единственное, что нужно установить $.support.cors = true; Тогда междоменный запрос отлично работает во всех браузерах для пользователей jquery.

Просто установите этот плагин jQuery: кросс-доменный JQuery AJAX для IE8

Этот плагин 1.4kb работает сразу в Internet Explorer 8 и 9.

Включите плагин после jQuery и вызовите ваш запрос ajax как обычно. Больше ничего не требуется.

Добавьте дополнительный транспорт в jquery для IE. (Просто добавьте этот код в свой скрипт в конце)

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

Это решило мою проблему с ошибкой Jquery $.ajax для кросс-доменного AJAX-запроса.

Приветствия.

Другие, приходящие сюда, могли бы хорошо прочитать http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx где говорится об ограничениях XDomainRequest

Для тех, у кого все еще может быть эта проблема с использованием jQuery 2.0 (я знаю, что знаю), Джей Дейв написал лучший обходной путь jQuery, но у меня еще есть несколько вещей, которые можно добавить к его коду, а именно:

  • Убедитесь, что вы используете тот же протокол для запросов (HTTP -> HTTP или HTTPS -> HTTPS), Аюш Гупта дал ссылку на известные проблемы
  • обрабатывать события onprogress с помощью функции no-op (это предотвратит прерывание запросов IE после получения первых битов от сервера.

Полный код ниже:

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

Просто добавьте "? Callback=?" (или "&callback=?") на ваш URL:

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

При выполнении вызовов (со всем остальным, правильно установленным для междоменной области, как указано выше), это вызовет правильное форматирование JSONP.

Более подробное объяснение можно найти в ответе здесь.

Обратите внимание, добавляя

$.support.cors = true;

было достаточно, чтобы заставить $.ajax работать на IE8

@Furqan Не могли бы вы сообщить мне, проверяли ли вы это методом HTTP POST,

Поскольку я также работаю над такой же ситуацией, но я не могу отправить данные в другой домен.

Но после прочтения это было довольно просто... единственное, что вы должны забыть о старых браузерах. Я даю код для отправки методом POST с того же выше URL для быстрой ссылки

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

У меня была похожая проблема в IE9, когда некоторые вызовы CORS прерывались, а другие нет. Мое приложение также зависит от интерфейса обещаний, поэтому приведенные выше предложения XDomainRequest не были ТОЧНО тем, что мне было нужно, поэтому я добавил отложенный вариант в обход service.get для IE9. Надеюсь, это может пригодиться кому-то, кто сталкивался с этой проблемой.:

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

Microsoft всегда пашет саморазрушающую (по крайней мере в IE) борозду:

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

CORS работает с XDomainRequest в IE8. Но IE 8 не поддерживает предварительные или учетные запросы, в то время как Firefox 3.5+, Safari 4+ и Chrome поддерживают такие запросы.

У меня та же проблема в IE, я решил ее, заменив:

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

к

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

Так что в основном обновите свою версию jquery.

Трудно сказать из-за отсутствия форматирования в вопросе, но я думаю, что вижу две проблемы с вызовом ajax.

1) application/x-www-form-urlencoded для contentType должен быть в кавычках

2) Должна быть запятая, разделяющая параметры contentType и async.

Другие вопросы по тегам