¿Cómo puedo producir JSONP desde un servicio web ASP.NET para llamadas entre dominios?

Escribí un servicio web que devuelve JSON y traté de llamarlo usando jQuery así:

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

Sin embargo, el código nunca llama a la función de éxito, a pesar de que la llamada al servicio web fue exitosa cuando se mira el tráfico HTTP con Fiddler. Creo que esto se debe a que mi servicio web está devolviendo JSON sin formato en lugar de JSONP.

¿Cómo puedo producir JSONP como la respuesta de un método de servicio web .NET estándar como este:

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

Gracias.

OK, eventualmente me di cuenta. Como me resultó muy difícil encontrar una solución de trabajo completa en la web, he decidido documentar mi solución de trabajo aquí.

Una respuesta JSONP es solo cadena estándar JSON envuelta en una llamada a función. ASP.NET no parece proporcionar ninguna forma de devolver la respuesta en este formato directamente, pero es muy simple hacerlo usted mismo. Sin embargo, debes sobrescribir el método predeterminado de encoding JSON.

A continuación se muestra un ejemplo de JSONP.

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

… ahora este bit: { name: 'value';} es solo JSON estándar que cualquier serializador JSON te dará, así que todo lo que tenemos que hacer es agregar el wrapper de llamadas a la función. Desafortunadamente, hacer eso significa que tenemos que “anular” (o eludir) la encoding JSON existente que maneja de forma transparente el marco cuando devuelve un objeto de la función del servicio web.

Esto se hace anulando por completo la respuesta de la función del servicio web escribiendo el JSONP en el flujo de salida (Response) usando nuestro propio código. Esto es bastante sencillo y he incluido un ejemplo a continuación.

Puede usar DataContractJsonSerializer incorporado (desde el espacio de nombres System.Runtime.Serialization.Json en ASP.NET 3.5+) o el serializador NewtonSoft JSON , y ambos ejemplos se muestran a continuación. Prefiero usar el NewtonSoft JSON (instalado desde Nuget) en lugar del serializador JSON integrado, ya que creo que le da más control y también puede generar JSON legible por humanos con buen formato para la depuración. ¡También es mucho más rápido en el papel!

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

Este método se puede llamar utilizando el siguiente código de 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 } 

Gracias Nick, esa fue una excelente respuesta a un problema que a mí también me costó encontrar al principio en línea. Funcionó muy bien para mí también.

Quería asegurarme de que esta línea de publicación recibiera la atención que merece.

Solo quería agregar que utilicé el serializador incorporado (System.Runtime.Serialization.Json) y funcionó como un amuleto también.

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

En caso de que alguien esté buscando una muestra de cómo devolver JSONP desde la acción de Web API ASP.NET :

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

JsonpResult auxiliar JsonpResult encapsula el envoltorio 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))); } } } }