2010-09-30 25 views
55

Tôi đang cố gắng lấy một số dữ liệu json từ một trang web "từ xa". Tôi chạy dịch vụ web của mình trên cổng 99000 rồi, tôi khởi chạy trang web của mình trên cổng 99001 (http: // localhost: 99001/index.html).XMLHttpRequest không thể tải một URL với jQuery

tôi nhận được thông báo sau:

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

Ngay cả Nếu tôi khởi động trang web của tôi dưới dạng tệp HTML, tôi có được điều này:

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

Số liệu lợi nhuận dịch vụ web. Tôi cố gắng nắm bắt những mục dữ liệu như thế này:

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

Và tôi đang cố gắng để có được cấu trúc này:

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

Bạn có biết lý do tại sao tôi nhận được lỗi này?

Trả lời

39

Bạn không thể làm một crossdomain XMLHttpRequest, các "lựa chọn" sẽ chỉ là một kỹ thuật gọi là JSONP, mà đi xuống đến này:

Để bắt đầu yêu cầu: Thêm một <script> thẻ mới với url từ xa, và sau đó đảm bảo rằng url từ xa trả về tệp javascript hợp lệ gọi hàm gọi lại của bạn. Một số dịch vụ hỗ trợ điều này (và cho phép bạn đặt tên cho gọi lại của bạn trong một tham số GET).

Cách khác dễ dàng nhất, là tạo một "proxy" trên máy chủ cục bộ của bạn, máy chủ này nhận yêu cầu từ xa và sau đó chỉ cần "chuyển tiếp" nó trở lại javascript của bạn.

chỉnh sửa/bổ sung:

tôi thấy jQuery đã xây dựng-in hỗ trợ cho JSONP, bằng cách kiểm tra nếu URL có chứa "? Callback =" (nơi jQuery sẽ thay thế? bằng phương thức gọi lại thực tế). Nhưng bạn vẫn cần phải xử lý điều đó trên máy chủ từ xa để tạo ra một phản hồi hợp lệ.

+9

Tôi đã giải quyết được sự cố bằng cách thêm "& callback =?" vào URL. Cảm ơn bạn! – Zakaria

+0

Tôi có phải chỉ định/thực hiện bất cứ điều gì trong kịch bản máy chủ trên máy chủ từ xa không? – j7nn7k

+0

Có, nơi máy chủ của bạn thường trả về một chuỗi JSON, ví dụ: '{" foo ":" bar "}' bạn cần bọc chuỗi json trong một phương thức gọi lại (hàm javascript) xử lý đáp ứng json. ví dụ. 'myFunction ({" foo ":" bar "});' – CharlesLeaf

33

Trong mới jQuery 1.5, bạn có thể sử dụng:

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

Không phải nó chỉ là "thành công: readData"? –

+2

Tôi gặp lỗi như SyntaxError: Mã thông báo không mong muốn: –

+0

Tôi đoán là có thêm ":" trong phản hồi của bạn. bạn có thể dán toàn bộ tin nhắn không? – Slavomir

19

Fiddle with 3 working solutions trong hành động.

Với một JSON bên ngoài:

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' 

Giải pháp 1: $ .ajax() + jsonp:

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

Giải pháp 2: $ .ajax() + json + & calback = ?:

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

Giải pháp 3: $ .getJSON() + calback =?:

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

Tài liệu tham: http://api.jquery.com/jQuery.ajax/, http://api.jquery.com/jQuery.getJSON/

+0

JSfiddle cố định sau thay đổi API #wikidata, cải thiện jsfiddle đã hoàn thành, cải thiện hiệu suất được thực hiện! – Hugolpz

+0

Không hoạt động trong ** HTTPS. ** Nhấp vào liên kết để xem https://jsfiddle.net/HNPyc/98/ –

+1

@TuhinPaul: khi bạn ở trên ** https ** fiddle bạn không thể yêu cầu ** http * * wikidata hoặc những người khác http, nó sẽ là một vi phạm an ninh. Bạn có thể thực hiện http-http, https-https hoặc http-https, không phải https-http. Đây là tính năng bảo mật, không phải là vấn đề về miền chéo. – Hugolpz

6

Tìm thấy một workaround có thể là tôi không tin được nhắc đến.

Dưới đây là một mô tả tốt của vấn đề: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Về cơ bản miễn là bạn sử dụng các hình thức/url-mã hóa các loại/plain nội dung văn bản bạn cũng tốt.

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

Tôi sử dụng nó với ASP.NET WebAPI2. Vì vậy, ở đầu bên kia:

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

Bằng cách này, trình định dạng Json được sử dụng khi phân tích cú pháp loại nội dung văn bản thuần túy.

Và đừng quên trong 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.

0

Tôi đang sử dụng WebAPI 3 và đang đối mặt với cùng một vấn đề. Vấn đề đã giải quyết khi @Rytis thêm giải pháp của anh ấy. Và tôi nghĩ trong WebAPI 3, chúng ta không cần phải định nghĩa phương thức RegisterWebApi.

Thay đổi của tôi chỉ ở tệp web.config và đang hoạt động.

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

Cảm ơn bạn đã giải pháp @Rytis!

Các vấn đề liên quan