Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

jquery - How can I produce JSONP from an ASP.NET web service for cross-domain calls?

I've written a webservice which returns JSON and I've tried to call it using jQuery like this:

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

However the code never calls the success function, despite the webservice call being successful when looking at the HTTP traffic using Fiddler. I think this is because my web service is returning raw JSON instead of JSONP.

How can I produce JSONP as the response from a standard .NET webservice method like this:

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

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

OK, I've eventually figured it out myself. As I found it so hard to find a complete working solution on the web, I've decided to document my working solution here.

A JSONP response is just standard JSON string wrapped in a function call. ASP.NET doesn't seem to provide any way to return the reponse in this format directly, but it's very simple to do this yourself. You do though, have to override the default method of JSON encoding.

Below is an example of JSONP.

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

..now this bit: { name: 'value';} is just standard JSON that any JSON serializer will give you, so all we need to do is tack on the function call wrapper. Unfortunately, doing that means we have to 'unwire' (or bypass) the existing JSON encoding which is handled transparently by the framework when you return an object from the web service function.

This is done by overriding the response from the web service function completely by writing the JSONP to the output stream (Response) using our own code. This is actually quite straightforward and I've included an example below.

You can use either the built in DataContractJsonSerializer (from the System.Runtime.Serialization.Json namespace in ASP.NET 3.5+) or the NewtonSoft JSON serializer, and both examples are shown below. I prefer to use the the NewtonSoft JSON (installed from nuget) rather than the built in JSON serializer as I find it gives you more control and also can output nicely formatted human readable JSON for debugging. It's also much faster on paper!

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

This method can then be called using the following JQuery code:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...