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

我写了一个返回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");} }); 

但是,尽管使用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; } 

谢谢。

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

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

然后可以使用以下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 } 

谢谢尼克,这是一个很好的答案,我也很难在网上找到一个问题。 对我来说也很棒。

希望确保这一系列的post得到应有的关注。

只想添加我使用内置的序列化器(System.Runtime.Serialization.Json),它也像魅力一样工作。

  List 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(); 

如果有人正在寻找示例如何从ASP.NET Web API操作返回JSONP

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

JsonpResult帮助类封装了JSONP包装。

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