Jquery $.Аякс не в 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 64

14 ответов:

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

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

EDIT (2013-08-22)

вторая ссылка мертв, поэтому я пишу здесь часть своей информации, взятой из wayback machine:

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

вместо того, чтобы реализовать версию CORS XMLHttpRequest, команда IE пошла с собственным объектом propriety, названным 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). Если вы посмотрите ниже, вы увидите, что это похоже на форматирование $.Аякс. Что касается моих исследований, я не могу заставить этот кросс-домен работать в IE6 & 7 (все еще ищу обходной путь для этого). XDR впервые вышел в IE8 (он также находится в IE9). Поэтому в основном сначала я тестирую 6/7 и не делаю AJAX.

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

после этого остальное, если тесты для ' XDomainRequest в окне (по-видимому, лучше, чем обнюхивание браузера) и делает запрос JSON 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.4 kb Работает сразу в 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-запрос.

Ура.

другие приходят сюда, возможно, хорошо бы прочитать 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), Ayush Gupta дал ссылку на knows issues
  • обрабатывать события "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=?") в свой адрес:

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

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

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

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

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

$.support.cors = true;

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

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.

У меня была аналогичная проблема в IE9, где некоторые вызовы CORS прерывались, а другие-нет. мое приложение также зависит от интерфейса promise, поэтому предложения XDomainRequest выше были не совсем тем, что мне нужно, поэтому я добавил отложенный в свою службу.получить обходной путь для 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
            });
        }
    }

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

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

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