2010-01-18 5 views
211

Ich versuche, einige JSON von einem WCF-Dienst zurückzugeben. Dieser Dienst gibt einfach einige Inhalte aus meiner Datenbank zurück. Ich kann die Daten bekommen. Ich bin jedoch besorgt über das Format meiner JSON. Derzeit ist die JSON, die wie dies wird zurückgegeben formatiert:Wie gebe ich sauberes JSON von einem WCF-Dienst zurück?

{"d":"[{\"Age\":35,\"FirstName\":\"Peyton\",\"LastName\":\"Manning\"},{\"Age\":31,\"FirstName\":\"Drew\",\"LastName\":\"Brees\"},{\"Age\":29,\"FirstName\":\"Tony\",\"LastName\":\"Romo\"}]"} 

In Wirklichkeit würde ich meine JSON gerne so sauber wie möglich formatiert werden. Ich glaube (ich könnte falsch sein), dass die gleiche Sammlung von Ergebnissen, in sauberen JSON dargestellt, wie so aussehen sollte:

[{"Age":35,"FirstName":"Peyton","LastName":"Manning"},{"Age":31,"FirstName":"Drew","LastName":"Brees"},{"Age":29,"FirstName":"Tony","LastName":"Romo"}] 

Ich habe keine Ahnung, wo die „d“ herkommt. Ich habe auch keine Ahnung, warum die Escape-Zeichen eingefügt werden. Meine Einheit sieht wie folgt aus:

[DataContract] 
public class Person 
{ 
    [DataMember] 
    public string FirstName { get; set; } 

    [DataMember] 
    public string LastName { get; set; } 

    [DataMember] 
    public int Age { get; set; } 

    public Person(string firstName, string lastName, int age) 
    { 
     this.FirstName = firstName; 
     this.LastName = lastName; 
     this.Age = age; 
    } 
} 

Der Dienst, der für die Rücksendung den Inhalt verantwortlich ist, wird wie folgt definiert:

[ServiceContract(Namespace = "")] 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
public class TestService 
{ 
    [OperationContract] 
    [WebGet(ResponseFormat = WebMessageFormat.Json)] 
    public string GetResults() 
    { 
     List<Person> results = new List<Person>(); 
     results.Add(new Person("Peyton", "Manning", 35)); 
     results.Add(new Person("Drew", "Brees", 31)); 
     results.Add(new Person("Tony", "Romo", 29)); 

     // Serialize the results as JSON 
     DataContractJsonSerializer serializer = new DataContractJsonSerializer(results.GetType()); 
     MemoryStream memoryStream = new MemoryStream(); 
     serializer.WriteObject(memoryStream, results); 

     // Return the results serialized as JSON 
     string json = Encoding.Default.GetString(memoryStream.ToArray()); 
     return json; 
    } 
} 

Wie kann ich zurückkehren „reinigen“ JSON aus einem WCF-Dienst? Vielen Dank!

+0

SOAP XML zurückgeben sollte. Sie können einen REST-Endpunkt verwenden, um JSON zurückzugeben. Werfen Sie einen Blick auf http://StackOverflow.com/questions/186631/rest-soap-endpoints-for-a-wcf-service/186695#186695 –

+4

Übrigens, wenn jemand anderes darüber stößt und fragt sich, warum das "d" Eigentum ist da, es ist da, um eine [JSON-Schwachstelle] zu patchen (http://haacked.com/archive/2008/11/20/anatomy-of-a-subltle-json-vulnerability.aspx/). Wenn du es entfernst, bist du wieder verwundbar. – Alex

+4

@Alex - diese Sicherheitslücke hängt davon ab, das Array-Objekt neu zu definieren, was in modernen Browsern nicht mehr möglich ist. Siehe http://stackoverflow.com/questions/16289894/is-json-hijacking-still-an-issue-in-moder-browsers – Cheeso

Antwort

195

Ändern Sie den Rückgabetyp Ihres GetResults in List<Person>.
Entfernen Sie den Code, den Sie verwenden, um die Liste zu einer JSON-Zeichenfolge zu serialisieren - WCF erledigt dies automatisch für Sie.

Ihre Definition für die Person-Klasse verwenden, funktioniert dieser Code für mich:

public List<Person> GetPlayers() 
{ 
    List<Person> players = new List<Person>(); 
    players.Add(new Person { FirstName="Peyton", LastName="Manning", Age=35 }); 
    players.Add(new Person { FirstName="Drew", LastName="Brees", Age=31 }); 
    players.Add(new Person { FirstName="Brett", LastName="Favre", Age=58 }); 

    return players; 
} 

Ergebnisse:

[{"Age":35,"FirstName":"Peyton","LastName":"Manning"}, 
{"Age":31,"FirstName":"Drew","LastName":"Brees"}, 
{"Age":58,"FirstName":"Brett","LastName":"Favre"}] 

(alles in einer Zeile)

habe ich auch dieses Attribut auf die Methode:

[WebInvoke(Method = "GET", 
      RequestFormat = WebMessageFormat.Json, 
      ResponseFormat = WebMessageFormat.Json, 
      UriTemplate = "players")] 

WebInvoke mit Methode = "GET" ist das gleiche wie WebGet, aber da einige meiner Methoden POST sind, verwende ich alle WebInvoke für die Konsistenz.

Die UriTemplate legt die URL fest, bei der die Methode verfügbar ist. So kann ich ein GET auf http://myserver/myvdir/JsonService.svc/players tun und es funktioniert einfach.

Überprüfen Sie auch IIRF oder einen anderen URL-Rewriter, um die .svc in der URI loszuwerden.

+0

Cheeso - Ich habe diesen Ansatz versucht, bevor ich diese Frage gestellt habe. Wenn ich diesen Ansatz verwende, erhalte ich einen Fehler, der besagt, dass "Endpoints, die 'UriTemplate' verwenden, nicht mit 'System.ServiceModel.Description.WebScriptEnablingBehavior' verwendet werden können." Was mache ich falsch? Vielen Dank! – user208662

+26

Verwenden Sie anstelle von in Ihrer .config-Datei. – Cheeso

+0

Ich bekomme den Fehler "Endpunkte mit ..." oben, aber habe in meiner web.config nirgends. Wo setze ich ? – MGOwen

87

Wenn Sie schöne json wollen, ohne Hardcoding in Ihre Service-Klassen-Attribute,

Verwendung <webHttp defaultOutgoingResponseFormat="Json"/> in Ihrem Verhalten Config

1

Wenn Sie GET verwenden Methode der Vertrag muss das sein.

[WebGet(UriTemplate = "/", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)] 
List<User> Get(); 

mit diesem haben wir eine json ohne Boot-Parameter

Aldo Flores @alduar http://alduar.blogspot.com

5

ich das gleiche Problem konfrontiert, und es gelöst, indem die Bodystyle Ausprägungswertänderung auf „WebMessageBodyStyle .Bare ":

[OperationContract] 
[WebGet(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, 
     ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetProjectWithGeocodings/{projectId}")] 
GeoCod_Project GetProjectWithGeocodings(string projectId); 

Das zurückgegebene Objekt wird nicht mehr umgebrochen ped.

0

In Ihrem IServece.cs fügen Sie den folgenden Tag: Bodystyle = WebMessageBodyStyle.Bare

[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "Getperson/{id}")] 

    List<personClass> Getperson(string id); 
+0

Kannst du auch erklären, warum BodyStyle das Ergebnis beeinflussen kann? – MBH

Verwandte Themen