如何从ASP.NET Web服务生成JSONP以进行跨域调用?

Nic*_*ckG 20 asp.net jquery jsonp cross-domain

我写了一个返回JSON的web服务,我试图用这样的jQuery调用它:

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

但是,尽管使用Fiddler查看HTTP流量时web服务调用成功,但代码从不调用成功函数.我认为这是因为我的Web服务正在返回原始JSON而不是JSONP.

如何生成JSONP作为标准.NET Web服务方法的响应,如下所示:

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

谢谢.

Nic*_*ckG 43

好吧,我最终自己弄明白了.由于我发现很难在网上找到完整的工作解决方案,所以我决定在这里记录我的工作解决方案.

JSONP响应只是函数调用中包含的标准JSON字符串.ASP.NET似乎没有提供任何方式直接以这种格式返回响应,但是自己这样做非常简单.但是,您必须覆盖JSON编码的默认方法.

以下是JSONP的示例.

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

..现在这一点: { name: 'value';} 只是任何JSON序列化程序都会给你的标准JSON,所以我们需要做的就是使用函数调用包装器.不幸的是,这样做意味着我们必须"无线化"(或旁路)现有的JSON这是当你从web服务的函数返回一个对象的框架透明地处理编码.

这是通过使用我们自己的代码将JSONP写入输出流(Response)来完全覆盖Web服务函数的响应来完成的.这实际上非常简单,我在下面列举了一个例子.

您可以使用内置的DataContractJsonSerializer(来自ASP.NET 3.5+中的System.Runtime.Serialization.Json命名空间)或NewtonSoft JSON序列化程序,这两个示例如下所示.我更喜欢使用NewtonSoft JSON(从nuget安装)而不是内置的JSON序列化器,因为我发现它可以为您提供更多控制,还可以输出格式良好的人类可读JSON进行调试.纸上的速度也快得多!

[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();
}
Run Code Online (Sandbox Code Playgroud)

然后可以使用以下JQuery代码调用此方法:

$.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
}
Run Code Online (Sandbox Code Playgroud)

  • 你救了我的一天:) (4认同)