我写了一个返回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;
}
感谢。
答案 0 :(得分: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();
}
然后可以使用以下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
}
答案 1 :(得分:3)
谢谢尼克,这是一个很好的答案,我也很难在网上找到这个问题。对我来说也很好。
希望确保这一帖子得到应有的关注。
只是想补充说我使用了内置的序列化程序(System.Runtime.Serialization.Json),它也像魅力一样。
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();
答案 2 :(得分:2)
如果有人正在寻找示例如何从JSONP
ASP.NET
行动中返回Web API
:
// 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)));
}
}
}
}