2010-01-18 15 views
211

Sto cercando di restituire alcuni JSON da un servizio WCF. Questo servizio restituisce semplicemente alcuni contenuti dal mio database. Posso ottenere i dati. Tuttavia, sono preoccupato per il formato del mio JSON. Attualmente, il JSON che viene restituito è formattato in questo modo:Come restituire JSON pulito da un servizio WCF?

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

In realtà, vorrei che la mia JSON da formattare in modo pulito come possibile. Credo che (io possa essere errato), che lo stesso insieme di risultati, rappresentato in JSON pulita, dovrebbe apparire in questo modo:

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

Non ho idea di dove la “d” proviene. Inoltre non ho idea del motivo per cui i caratteri di escape vengono inseriti. Il mio soggetto è simile al seguente:

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

Il servizio che è responsabile della restituzione del contenuto è definito come:

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

Come faccio a restituire “pulito” JSON da un servizio WCF? Grazie!

+0

SOAP deve restituire XML. È possibile utilizzare un endpoint REST per restituire JSON. Date un'occhiata http://stackoverflow.com/questions/186631/rest-soap-endpoints-for-a-wcf-service/186695#186695 –

+4

A proposito, se qualcun altro si imbatte in questo e si chiede perché la "d" la proprietà è lì, è lì per correggere una [vulnerabilità JSON] (http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/). Rimozione lo rende di nuovo vulnerabile. – Alex

+4

@Alex: la vulnerabilità dipende dalla ridefinizione dell'oggetto Array, che non è più possibile nei browser moderni. Vedi http://stackoverflow.com/questions/16289894/is-json-hijacking-still-an-issue-in-modern-browsers – Cheeso

risposta

195

Modificare il tipo di restituzione dei GetResults da List<Person>.
Elimina il codice che usi per serializzare l'elenco su una stringa json - WCF lo fa automaticamente.

Utilizzando la vostra definizione per la classe Person, questo codice funziona per me:

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

risultati:

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

(tutto su una riga)

ho usato anche questo attributo su il metodo:

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

WebInvoke con Method = "GET" è lo stesso di WebGet, ma dal momento che alcuni dei miei metodi sono POST, utilizzo tutto il WebInvoke per coerenza.

UriTemplate imposta l'URL a cui è disponibile il metodo. Quindi posso fare un GET su http://myserver/myvdir/JsonService.svc/players e funziona.

Controllare inoltre IIRF o un altro rewriter URL per eliminare .svc nell'URI.

+0

Cheeso - Ho provato questo approccio prima di pubblicare questa domanda. Quando utilizzo questo approccio, viene visualizzato un errore che dice "Gli endpoint che utilizzano UriTemplate non possono essere utilizzati con" System.ServiceModel.Description.WebScriptEnablingBehavior "." Che cosa sto facendo di sbagliato? Grazie! – user208662

+26

usa invece di nel tuo file .config. – Cheeso

+0

Sto ricevendo l'errore "endpoint usando ..." sopra ma non ho nel mio web.config ovunque. dove metto ? – MGOwen

87

Se si desidera bel JSON senza hardcoding attributi nelle vostre classi di servizio,

uso <webHttp defaultOutgoingResponseFormat="Json"/> nella configurazione del comportamento

1

Quando si utilizza metodo GET il contratto deve essere questo.

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

con questo abbiamo un JSON senza il parametro di boot

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

5

Ho affrontato lo stesso problema, e risolto cambiando il valore BodyStyle attribut a "WebMessageBodyStyle .Bare ":

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

L'oggetto restituito non verrà più avvolto ped.

0

Nelle tue IServece.cs aggiungere il seguente tag: BodyStyle = WebMessageBodyStyle.Bare

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

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

puoi anche spiegare perché BodyStyle può influenzare il risultato? – MBH

Problemi correlati