2013-01-08 5 views
20

Ich habe eine Webservice geschrieben, die JSON zurückgibt, und ich habe versucht, es zu nennen diese jQuery wie mit:Wie kann ich JSONP über einen ASP.NET-Webdienst für domänenübergreifende Aufrufe erstellen?

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

jedoch der Code nie den Erfolg Funktion aufruft, trotz der Webservice Aufruf erfolgreich sein, wenn sie bei der Suche HTTP-Verkehr mit Fiddler. Ich denke, das liegt daran, dass mein Web-Service JSON-Rohdaten anstelle von JSONP zurückgibt.

Wie kann ich produzieren JSONP als Antwort von einem Standard .NET Webservice Methode wie folgt:

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

Dank.

+0

ich es nur mit einem ASP.Net Web-API auf dieser Basis getan haben: http://stackoverflow.com/a/9422178/585552 es Ihnen ein paar Ideen können ... – Greg

+0

Versuchen Hinzufügen 'Antwort .AddHeader ("Access-Control-Allow-Origin", "*") 'im Hauptteil der Web-Methode – Icarus

Antwort

43

OK, ich habe es irgendwann selbst herausgefunden. Da ich es so schwer fand, eine komplette funktionierende Lösung im Internet zu finden, habe ich beschlossen, meine Arbeitslösung hier zu dokumentieren.

Eine JSONP-Antwort ist nur eine Standard-JSON-Zeichenfolge, die in einem Funktionsaufruf enthalten ist. ASP.NET scheint keine Möglichkeit zu bieten, die Antwort in diesem Format direkt zurückzugeben, aber es ist sehr einfach, dies selbst zu tun. Sie müssen jedoch die Standardmethode der JSON-Codierung überschreiben.

Im Folgenden finden Sie ein Beispiel für JSONP.

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

..now dieses Bit: { name: 'value';} ist nur Standard JSON, die jeder JSON Serializer Sie geben, so alles, was wir tun müssen, ist Tack auf dem Wrapper-Funktionsaufruf. Leider bedeutet dies, dass wir die vorhandene JSON-Codierung, die transparent vom Framework gehandhabt wird, wenn Sie ein Objekt von der Web-Service-Funktion zurückgeben, "unwirbeln" (oder umgehen) müssen.

Dies geschieht durch Überschreiben der Antwort von der Web-Service-Funktion vollständig durch Schreiben der JSONP in den Ausgabestream (Response) mit unserem eigenen Code. Das ist eigentlich ziemlich einfach und ich habe ein Beispiel unten eingefügt.

Sie können entweder den eingebauten DataContractJsonSerializer (aus dem Namespace System.Runtime.Serialization.Json in ASP.NET 3.5+) oder den NewtonSoft JSON Serializer verwenden, und beide Beispiele werden unten gezeigt. Ich bevorzuge die Verwendung der NewtonSoft JSON (installiert von Nuget) anstelle der eingebauten JSON-Serializer, wie ich finde es gibt Ihnen mehr Kontrolle und kann auch schön formatierte menschenlesbare JSON zum Debuggen ausgeben. Es ist auch viel schneller auf dem Papier!

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

Diese Methode kann dann Code mit dem folgende JQuery aufgerufen werden:

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

Sie haben meinen Tag gerettet :) – Exor

+0

Sie haben' callback' in Ajax-Anfrage nicht gesendet. Wie konnten Sie es in C# Methode erhalten? – Sami

+1

@Sami - es wird automatisch von JQuery – NickG

3

Dank Nick, das war eine ausgezeichnete Antwort auf ein Problem, das ich hatte auch eine harte Zeit auf dem ersten Online-Suche. Hat auch super funktioniert.

Wollte sicherstellen, dass diese Linie der Post die Aufmerksamkeit bekam, die sie verdient.

Ich wollte nur hinzufügen, dass ich den eingebauten Serializer (System.Runtime.Serialization.Json) verwendet und es funktionierte wie ein Charme auch.

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

Falls jemand für Probe suchen, wie JSONP von ASP.NETWeb API Aktion zurück:

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

JsonpResult die JSONP Verpackung Einkapseln Hilfsklasse.

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