web-dev-qa-db-fra.com

Jquery $ .ajax échoue dans IE sur les appels entre domaines

Je suis en train de faire une requête interdomaine en utilisant $.ajax. Cela fonctionne sur Firefox et Chrome, mais ne passe pas d'appel sur IE 7 ou 8. Quelqu'un peut-il me dire ce qui ne va pas avec ce qui suit?

  1. J'ai utilisé JSON et JSONP (que j'ai arrêté d'utiliser en raison de certaines restrictions personnalisées).
  2. J'utilise déjà Allow-access-control-Origin en-tête sur mon site. (Sans ceux-ci, Chrome et Firefox ne faisaient pas les demandes avec succès.)
  3. J'ai déjà essayé 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);
    }
});

J'ai essayé divers conseils présents sur plusieurs sites, mais pas de chance pour le moment.

64
Furqan Hameedi

Pourriez-vous vérifier si le problème avec IE ne repose pas sur la définition de zones de sécurité pour autoriser les requêtes entre domaines? voir cette page Microsoft pour une explication.

OTOH, cette page indique que IE7 et Eariler ne peuvent pas effectuer d'appels entre domaines, mais qu'IE8 peut, à l'aide d'un objet différent de XMLHttpRequest, celui utilisé par JQuery. Pourriez-vous vérifier si XDomainRequest fonctionne?

EDIT (2013-08-22)

Le deuxième lien est mort, j'écris donc ici certaines de ses informations, tirées de la machine à remonter le temps :

XDomainRequest pris en charge: IE8

Plutôt que d'implémenter la version CORS de XMLHttpRequest, l'équipe IE est allée avec son propre objet de propriété, nommée XDomainRequest. L'utilisation de XDomainRequest a été simplifiée (avec onload). peut-être le plus important).

Cette implémentation a quelques limitations qui s’y rattachent. Par exemple, les cookies ne sont pas envoyés lors de l'utilisation de cet objet, ce qui peut être un casse-tête pour les sessions basées sur les cookies côté serveur. De plus, ContentType ne peut pas être défini, ce qui pose un problème dans ASP.NET et éventuellement dans d'autres langages côté serveur (voir 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();
32
Luciano

Pour IE8 et IE9, vous devez utiliser XDomainRequest (XDR). Si vous regardez ci-dessous, vous verrez que son formatage est similaire à celui de $ .ajax. En ce qui concerne mes recherches, je ne parviens pas à faire fonctionner ce domaine transversal dans IE6 & 7 (je cherche toujours une solution de rechange pour cela). XDR est apparu pour la première fois dans IE8 (également dans IE9). En gros, d’abord, j’ai testé 6/7 et je n’ai pas d’Ajax.

IE10 + est capable de faire interdomaine normalement comme tous les autres navigateurs (félicitations Microsoft ... soupir)

Après cela, else si teste pour 'XDomainRequest dans la fenêtre (apparemment mieux que le sniffing du navigateur) et fait le JSON AJAX demande de cette façon, sinon l'ELSE le fait normalement avec $ .ajax.

J'espère que cela t'aides!! Il m'a fallu une éternité pour comprendre tout cela à l'origine

informations sur l'objet 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);
            }
        });
    }
}
62

Jquery le fait pour vous, la seule chose à faire est de définir $.support.cors = true; La requête interdomaine fonctionne alors dans tous les navigateurs pour les utilisateurs de jQuery.

23
Anand

Installez simplement ce plugin jQuery: jQuery Cross-Domain AJAX pour IE8

Ce plugin de 1,4 Ko fonctionne immédiatement dans Internet Explorer 8 et 9 .

Incluez le plugin après jQuery et appelez votre demande ajax comme d'habitude. Rien d'autre requis.

20
Bradley Flood

Ajoutez un moyen de transport supplémentaire à jQuery pour IE. (Ajoutez simplement ce code dans votre script à la fin)

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

Cela a résolu mon problème avec Jquery $ .ajax échouant pour Cross Domain AJAX request.

À votre santé.

7
Jay Dave

D'autres venant ici pourraient faire bien de lire http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx parle des limitations de XDomainRequest

5
Ayush Gupta

Pour ceux qui ont encore ce problème en utilisant jQuery 2.0 (je sais que je le sais), Jay Dave a écrit la meilleure solution de contournement de jQuery, mais il me reste encore quelques choses à ajouter à son code, à savoir:

  • assurez-vous que vous utilisez le même protocole pour les demandes (HTTP -> HTTP ou HTTPS -> HTTPS), Ayush Gupta a indiqué un lien vers les problèmes connus
  • gérer les événements "onprogress" avec une fonction no-op (cela empêchera IE de traiter les requêtes après avoir reçu les premiers bits du serveur).

Le code complet est ci-dessous:

// 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();
            }
        };
    });
}
3
alecs.popa

Ajoutez simplement "? Callback =?" (ou "& callback =?") à votre URL:

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

Lorsque vous effectuez des appels (avec tout le reste défini correctement pour inter-domaine, comme ci-dessus), le formatage JSONP approprié est déclenché.

Des explications plus détaillées peuvent être trouvées dans la réponse ici .

2
Randy Hall

Notez, en ajoutant

$.support.cors = true;

était suffisant pour forcer $ .ajax appels à travailler sur IE8

2
jpantona

@Furqan Pourriez-vous s'il vous plaît laissez-moi savoir si vous avez testé cela avec HTTP POST méthode,

Depuis que je travaille aussi sur le même genre de situation, mais je ne suis pas capable de POST les données dans un domaine différent.

Mais après avoir lu this c'était assez simple ... la seule chose à faire est d’oublier les vieux navigateurs. Je donne le code à envoyer avec POST à partir de la même URL ci-dessus pour une référence rapide

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
Sandesh Daddi

Microsoft sillonne toujours un sillon contre-productif (au moins dans IE):

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

CORS fonctionne avec XDomainRequest dans IE8. Mais IE 8 ne prend pas en charge les demandes pré-contrôlées ou accréditées tandis que Firefox 3.5+, Safari 4+ et Chrome prennent toutes en charge de telles demandes.

0
Raman

J'ai eu un problème similaire dans IE9 où certains appels de la CORS étaient abandonnés, alors que d'autres ne l'étaient pas. Mon application dépend également d'une interface de promesse. Par conséquent, les suggestions XDomainRequest ci-dessus n'étaient pas exactement ce dont j'avais besoin. J'ai donc ajouté une solution de contournement service.get à IE9. Espérons que cela puisse être utile à quelqu'un qui rencontre ce problème. :

    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
            });
        }
    }
0
David Savage

J'ai le même problème dans IE, je l'ai résolu en remplaçant:

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

Donc, fondamentalement, mettez à niveau votre version de jquery.

0
KingBowen