Come posso produrre JSONP da un servizio Web ASP.NET per le chiamate tra domini diversi?

Ho scritto un webservice che restituisce JSON e ho provato a chiamarlo usando jQuery in questo modo:

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

Tuttavia, il codice non chiama mai la funzione di successo, nonostante la chiamata al servizio web abbia successo quando esamina il traffico HTTP usando Fiddler. Penso che questo sia dovuto al fatto che il mio servizio web restituisce JSON non elaborato anziché JSONP.

Come posso produrre JSONP come risposta da un metodo webservice .NET standard come questo:

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

Grazie.

OK, alla fine ho capito da solo. Poiché ho trovato così difficile trovare una soluzione di lavoro completa sul web, ho deciso di documentare la mia soluzione di lavoro qui.

Una risposta JSONP è solo una stringa JSON standard racchiusa in una chiamata di funzione. ASP.NET non sembra fornire alcun modo per restituire direttamente la risposta in questo formato, ma è molto semplice farlo da solo. Tuttavia, devi eseguire l’override del metodo predefinito di codifica JSON.

Di seguito è riportato un esempio di JSONP.

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

..ora questo bit: { name: 'value';} è solo JSON standard che qualsiasi serializer JSON ti fornirà, quindi tutto ciò che dobbiamo fare è virare sulla funzione call wrapper. Sfortunatamente, facendo ciò significa che dobbiamo “non utilizzare” (o bypassare) la codifica JSON esistente che viene gestita in modo trasparente dal framework quando si restituisce un object dalla funzione del servizio web.

Ciò avviene sovrascrivendo completamente la risposta dalla funzione del servizio Web scrivendo il JSONP allo stream di output (Response) utilizzando il nostro codice. Questo è in realtà abbastanza semplice e ho incluso un esempio qui sotto.

È ansible utilizzare sia il DataContractJsonSerializer incorporato (dallo spazio dei nomi System.Runtime.Serialization.Json in ASP.NET 3.5+) o il serializzatore JSON NewtonSoft , ed entrambi gli esempi sono mostrati di seguito. Io preferisco usare il JSON NewtonSoft (installato da nuget) piuttosto che il serializzatore JSON incorporato, perché trovo che ti dà più controllo e può anche produrre JSON leggibile dall’uomo, ben formattato, per il debug. È anche molto più veloce sulla carta!

 [WebMethod()] [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] public void GetData(int projectID, string callback) { List

Questo metodo può quindi essere chiamato utilizzando il seguente codice 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 } 

Grazie Nick, questa è stata un’ottima risposta a un problema che ho avuto anch’io difficoltà a trovare online. Ha funzionato benissimo anche per me.

Volevo assicurarmi che questa linea di post avesse l’attenzione che meritava.

Volevo solo aggiungere che ho usato il serializzatore integrato (System.Runtime.Serialization.Json) e ha funzionato come un fascino.

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

Nel caso in cui qualcuno stia cercando un esempio su come restituire JSONP dall’azione Web API ASP.NET :

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

JsonpResult helper JsonpResult incapsula il wrapping 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))); } } } }