web-dev-qa-db-fra.com

XMLHttpRequest ne peut pas charger une URL avec jQuery

J'essaie d'obtenir des données JSON d'un site Web "distant". Je lance mon service Web sur le port 99000, puis je lance mon site Web sur le port 99001 (http: // localhost: 99001/index.html).

Je reçois le message suivant:

    XMLHttpRequest cannot load http://localhost:99000/Services.svc/ReturnPersons. Origin http://localhost:99001 is not allowed by Access-Control-Allow-Origin.

Même si je lance ma page Web en tant que fichier HTML, je reçois ceci:

    XMLHttpRequest cannot load http://localhost:99000/Services.svc/ReturnPersons.Origin null is not allowed by Access-Control-Allow-Origin.

Le service Web renvoie des données. J'essaie d'attraper les éléments de données comme ceci:

var url = "http://localhost:99000/Services.svc/ReturnPersons";
$.getJSON(url, function (data) {
success: readData(data)
});
function readData(data) {
    alert(data[0].FirstName);
}

Et j'essaie d'obtenir cette structure:

[{"FirstName":"Foo","LastName":"Bar"},{"Hello":"Foo","LastName":"World"}]

Savez-vous pourquoi je reçois cette erreur?

55
Zakaria

Vous ne pouvez pas faire de crossdomain XMLHttpRequest, la seule "option" serait une technique appelée JSONP, qui se résume à ceci:

Pour lancer la demande: Ajouter un nouveau <script> avec l’URL distante, puis assurez-vous que cette URL renvoyée renvoie un fichier JavaScript valide qui appelle votre fonction de rappel. Certains services prennent en charge cette fonctionnalité (et vous permettent de nommer votre rappel dans les paramètres GET).

L’autre solution de facilité consiste à créer un "proxy" sur votre serveur local, qui récupère la demande à distance puis la "transmet" à votre javascript.

éditer/additionner

Je vois que jQuery a un support intégré pour JSONP, en vérifiant si l'URL contient "callback =?" (où jQuery remplacera? par la méthode de rappel actuelle). Mais vous devez toujours traiter cela sur le serveur distant pour générer une réponse valide.

39
CharlesLeaf

Dans le nouveau jQuery 1.5, vous pouvez utiliser:

$.ajax({
    type: "GET",
    url: "http://localhost:99000/Services.svc/ReturnPersons",
    dataType: "jsonp",
    success: readData(data),
    error: function (xhr, ajaxOptions, thrownError) {
      alert(xhr.status);
      alert(thrownError);
    }
})
34
Slav

Fiddle avec 3 solutions de travail en action.

Étant donné un JSON externe:

myurl = 'http://wikidata.org/w/api.php?action=wbgetentities&sites=frwiki&titles=France&languages=zh-hans|zh-hant|fr&props=sitelinks|labels|aliases|descriptions&format=json'

Solution 1: $ .ajax () + jsonp:

$.ajax({
  dataType: "jsonp",
  url: myurl ,
  }).done(function ( data ) {
  // do my stuff
});

Solution 2: $ .ajax () + json + & calback = ?:

$.ajax({
  dataType: "json",
  url: myurl + '&callback=?',
  }).done(function ( data ) {
  // do my stuff
});

Solution 3: $ .getJSON () + calback = ?:

$.getJSON( myurl + '&callback=?', function(data) {
  // do my stuff
});

Documentations: http://api.jquery.com/jQuery.ajax/ , http://api.jquery.com/jQuery.getJSON/

19
Hugolpz

J'ai trouvé une solution de contournement qui, à mon avis, n'a pas été mentionnée.

Voici une bonne description du problème: http://www.asp.net/web-api/overview/security/enabling-cross-Origin-requests-in-web-api

Fondamentalement, tant que vous utilisez des types de contenu de type textes/texte codé/url, tout va bien.

$.ajax({
    type: "POST",
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'text/plain'
    },
    dataType: "json",
    url: "http://localhost/endpoint",
    data: JSON.stringify({'DataToPost': 123}),
    success: function (data) {
        alert(JSON.stringify(data));
    }
});     

Je l'utilise avec ASP.NET WebAPI2. Donc à l'autre bout:

public static void RegisterWebApi(HttpConfiguration config)
{
    config.MapHttpAttributeRoutes();

    config.Formatters.Clear();
    config.Formatters.Add(new JsonMediaTypeFormatter());

    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
}

De cette façon, le formateur Json est utilisé lors de l'analyse du type de contenu en texte brut.

Et n'oubliez pas dans Web.config:

<system.webServer>
<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="GET, POST" />
  </customHeaders>
</httpProtocol>    

J'espère que cela t'aides.

6
Rytis

J'utilise WebAPI 3 et je faisais face au même problème. Le problème a résolu lorsque @Rytis a ajouté sa solution. Et je pense que dans WebAPI 3, nous n’avons pas besoin de définir la méthode RegisterWebApi.

Mon changement était uniquement dans le fichier web.config et fonctionne.

<httpProtocol>
 <customHeaders>
 <add name="Access-Control-Allow-Origin" value="*" />
 <add name="Access-Control-Allow-Methods" value="GET, POST" />
</customHeaders>
</httpProtocol> 

Merci pour votre solution @Rytis!

0
Navin Pandit