XMLHttpRequest cannot load an URL with jQuery

2019-01-01 12:39发布

问题:

I\'m trying to get some json data from a \"remote\" website. I run my web service on the 99000 port then, I launch my website on the 99001 port (http://localhost:99001/index.html).

I get the following message:

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

Even If I launch my web page as an HTML file, I get this:

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

The web service returns data. I try to catch the data items like this:

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

And I\'m trying to get this structure:

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

Do you know why I\'m getting this error?

回答1:

You can\'t do a XMLHttpRequest crossdomain, the only \"option\" would be a technique called JSONP, which comes down to this:

To start request: Add a new <script> tag with the remote url, and then make sure that remote url returns a valid javascript file that calls your callback function. Some services support this (and let you name your callback in a GET parameters).

The other easy way out, would be to create a \"proxy\" on your local server, which gets the remote request and then just \"forwards\" it back to your javascript.

edit/addition:

I see jQuery has built-in support for JSONP, by checking if the URL contains \"callback=?\" (where jQuery will replace ? with the actual callback method). But you\'d still need to process that on the remote server to generate a valid response.



回答2:

In new jQuery 1.5 you can use:

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


回答3:

Fiddle with 3 working solutions in action.

Given an external JSON:

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/



回答4:

Found a possible workaround that I don\'t believe was mentioned.

Here is a good description of the problem: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Basically as long as you use forms/url-encoded/plain text content types you are fine.

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

I use it with ASP.NET WebAPI2. So on the other end:

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

This way Json formatter gets used when parsing plain text content type.

And don\'t forget in Web.config:

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

Hope this helps.



回答5:

I am using WebAPI 3 and was facing the same issue. The issue has resolve as @Rytis added his solution. And I think in WebAPI 3, we don\'t need to define method RegisterWebApi.

My change was only in web.config file and is working.

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

Thanks for you solution @Rytis!