2013-01-08 39 views
20

Tôi đã viết một webservice trả về JSON và tôi đã cố gắng để gọi nó là sử dụng jQuery như thế này:Làm cách nào để tạo JSONP từ dịch vụ web ASP.NET cho các cuộc gọi tên miền chéo?

$.ajax({ 
    contentType: "application/json; charset=utf-8", 
    url: "http://examplewebsite.com/service.asmx/GetData", 
    data: { projectID: 1 }, 
    dataType: "jsonp", 
    success: function() {alert("success");} 
}); 

Tuy nhiên mã không bao giờ gọi hàm thành công, bất chấp các cuộc gọi webservice thành công khi nhìn vào Lưu lượng truy cập HTTP bằng Fiddler. Tôi nghĩ điều này là do dịch vụ web của tôi trả về JSON thô thay vì JSONP.

Làm thế nào tôi có thể sản xuất JSONP như phản hồi từ một phương pháp NET WebService tiêu chuẩn như thế này:

[WebMethod(), ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] 
public Project GetData(int projectID) 
{ 
    Project p = new Project(); 
    p.Name = "foobar"; 
    return p; 
} 

Cảm ơn.

+0

Tôi chỉ thực hiện nó với một API Web ASP.Net dựa trên này: http://stackoverflow.com/a/9422178/585552 nó có thể cung cấp cho bạn một số ý tưởng ... – Greg

+0

Hãy thử thêm 'đáp ứng .AddHeader ("Access-Control-Allow-Origin", "*") 'trong nội dung của Phương thức Web – Icarus

Trả lời

43

OK, cuối cùng tôi đã tự tìm ra. Vì tôi thấy khó tìm được giải pháp làm việc hoàn chỉnh trên web, tôi đã quyết định viết tài liệu cho giải pháp làm việc của mình tại đây.

Phản hồi JSONP chỉ là chuỗi JSON chuẩn được bao bọc trong một cuộc gọi hàm. ASP.NET dường như không cung cấp bất kỳ cách nào để trả lại phản hồi theo định dạng này trực tiếp, nhưng nó rất đơn giản để tự làm điều này. Bạn làm điều đó, phải ghi đè lên phương thức mặc định của mã hóa JSON.

Dưới đây là ví dụ về JSONP.

functionName({ name: 'value';});

..now bit này: { name: 'value';} chỉ là JSON tiêu chuẩn mà bất kỳ serializer JSON sẽ cung cấp cho bạn, vì vậy tất cả chúng ta cần phải làm là tack trên wrapper chức năng cuộc gọi. Thật không may, làm điều đó có nghĩa là chúng ta phải 'unwire' (hoặc bỏ qua) mã hóa JSON hiện có được xử lý một cách minh bạch bởi khung công tác khi bạn trả về một đối tượng từ chức năng dịch vụ web.

Điều này được thực hiện bằng cách ghi đè phản hồi từ chức năng dịch vụ web hoàn toàn bằng cách viết JSONP vào luồng đầu ra (Trả lời) bằng mã riêng của chúng tôi. Điều này thực sự khá đơn giản và tôi đã bao gồm một ví dụ bên dưới.

Bạn có thể sử dụng hoặc được xây dựng trong DataContractJsonSerializer (từ không gian tên System.Runtime.Serialization.Json trong ASP.NET 3.5+) hoặc bộ nối tiếp NewtonSoft JSON và cả hai ví dụ được hiển thị bên dưới. Tôi thích sử dụng các NewtonSoft JSON (cài đặt từ nuget) hơn là xây dựng trong serializer JSON như tôi tìm thấy nó mang lại cho bạn kiểm soát nhiều hơn và cũng có thể sản xuất JSON định dạng độc đáo có thể đọc được để gỡ lỗi. Nó cũng nhanh hơn rất nhiều trên giấy!

[WebMethod()] 
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] 
public void GetData(int projectID, string callback) 
{ 
    List<Video> videos = null; 
    // <code here to populate list on line above> 

    // Method 1: use built-in serializer: 
    StringBuilder sb = new StringBuilder(); 
    JavaScriptSerializer js = new JavaScriptSerializer(); 
    sb.Append(callback + "("); 
    sb.Append(js.Serialize(videos)); 
    sb.Append(");");  

    // Method 2: NewtonSoft JSON serializer (delete as applicable) 
    // StringBuilder sb = new StringBuilder(); 
    // sb.Append(callback + "("); 
    // sb.Append(JsonConvert.SerializeObject(videos, Formatting.Indented)); // indentation is just for ease of reading while testing 
    // sb.Append(");");  

    Context.Response.Clear(); 
    Context.Response.ContentType = "application/json"; 
    Context.Response.Write(sb.ToString()); 
    Context.Response.End(); 
} 

Phương pháp này sau đó có thể được gọi bằng mã JQuery sau:

$.ajax({ 
    crossDomain: true, 
    contentType: "application/json; charset=utf-8", 
    url: "http://examplewebsite.com/service.asmx/GetData", 
    data: { projectID: 1 }, // example of parameter being passed 
    dataType: "jsonp", 
    success: onDataReceived 
}); 

function onDataReceived(data) 
{ 
    alert("Data received"); 
    // Do your client side work here. 
    // 'data' is an object containing the data sent from the web service 
    // Put a JS breakpoint on this line to explore the data object 
} 
+4

Bạn đã lưu ngày của tôi :) – Exor

+0

Bạn đã không gửi' callback' trong yêu cầu ajax. Làm thế nào bạn có thể nhận được nó trong phương pháp C#? – Sami

+1

@Sami - nó được tự động thêm vào bởi JQuery – NickG

3

Cảm ơn Nick, đó là một câu trả lời tuyệt vời cho một vấn đề mà tôi cũng có một thời gian khó tìm lúc đầu trực tuyến. Làm việc rất tốt cho tôi.

Muốn đảm bảo dòng này của bài đăng có được sự chú ý, nó xứng đáng.

Chỉ muốn thêm rằng tôi đã sử dụng bộ nối tiếp tích hợp sẵn (System.Runtime.Serialization.Json) và nó cũng hoạt động như một nét duyên dáng.

 List<orderHistory> orderHistory = null; 

     StringBuilder sb = new StringBuilder(); 
     JavaScriptSerializer js = new JavaScriptSerializer(); 
     sb.Append(callback + "("); 
     sb.Append(js.Serialize(orderHistory)); 
     sb.Append(");"); 

     Context.Response.Clear(); 
     Context.Response.ContentType = "application/json"; 
     Context.Response.Write(sb.ToString()); 
     Context.Response.End(); 
0

Trong trường hợp ai đó đang tìm kiếm mẫu làm thế nào để trở JSONP từ ASP.NETWeb API hành động:

// GET api/values 
public JsonpResult Get() 
{ 
    var values = new string[] { "value1", "value2" }; 
    return new JsonpResult(values); 
} 

JsonpResult lớp helper đóng gói JSONP gói.

public class JsonpResult : JsonResult 
{ 
    object _data = null; 

    public JsonpResult(object Data) 
    { 
     _data = Data; 
    } 

    public override void ExecuteResult(ControllerContext controllerContext) 
    { 
     if (controllerContext != null) 
     { 
      var Response = controllerContext.HttpContext.Response; 
      var Request = controllerContext.HttpContext.Request; 

      var callBackFunction = Request["callback"]; 
      if (string.IsNullOrEmpty(callBackFunction)) 
      { 
       throw new Exception("Callback function name must be provided in the request!"); 
      } 
      Response.ContentType = "application/x-javascript"; 
      if (_data != null) 
      { 
       var serializer = new JavaScriptSerializer(); 
       Response.Write(string.Format("{0}({1});", callBackFunction, serializer.Serialize(Data))); 
      } 
     } 
    } 
} 
Các vấn đề liên quan