Come posso restituire JSON pulito da un servizio WCF?


233

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:

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

In realtà, vorrei che il mio JSON fosse formattato nel modo più pulito possibile. Credo (potrei essere errato), che la stessa raccolta di risultati, rappresentata in JSON pulito, dovrebbe apparire così:

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

Non ho idea da dove provenga la "d". Inoltre non ho idea del perché vengano inseriti i caratteri di escape. La mia entità è simile alla 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 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 posso restituire JSON "pulito" da un servizio WCF? Grazie!


SOAP dovrebbe restituire XML. È possibile utilizzare un endpoint REST per restituire JSON. Dai un'occhiata a stackoverflow.com/questions/186631/…
Akira Yamamoto,

4
A proposito, se qualcun altro si imbatte in questo e si chiede perché la proprietà "d" sia lì, è lì per correggere una vulnerabilità JSON . Rimuoverlo ti rende di nuovo vulnerabile.
Alex,

4
@Alex - la vulnerabilità dipende dalla ridefinizione dell'oggetto Array, che non è più possibile nei browser moderni. Vedere stackoverflow.com/questions/16289894/...
Cheeso

Quello è buono. :) La metà della mia risposta è comunque vera: era lì per correggere quella vulnerabilità.
Alex,

Risposte:


213

Modificare il tipo di ritorno di GetResults in modo che sia List<Person>.
Elimina il codice che usi per serializzare l'Elenco su una stringa JSON - WCF lo fa automaticamente per te.

Usando la tua 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;
}

i risultati:

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

(Tutto su una riga)

Ho anche usato questo attributo sul metodo:

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

WebInvoke with Method = "GET" è uguale a WebGet, ma poiché alcuni dei miei metodi sono POST, utilizzo sempre WebInvoke per coerenza.

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

Controlla anche IIRF o un altro rewriter URL per eliminare .svc nell'URI.


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

28
usa <webHttp /> invece di <webScriptEnablingBehavior /> nel tuo file .config.
Cheeso,

9
OK, ho sostituito <enableWebScript /> con <webHttp /> e ha funzionato.
MGOwen,

3
MGowen - Cordiali saluti, la cosa migliore da fare quando si fa una nuova domanda è ... aprire una nuova domanda, piuttosto che pubblicare la domanda come commento a una vecchia risposta.
Cheeso,

5
Favre vede cosa hai fatto lì.
ruffin,

93

Se vuoi un buon json senza attributi hardcoding nelle tue classi di servizio,

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



8

Ho riscontrato lo stesso problema e risolto modificando il valore di attributo BodyStyle in "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ù spostato.


1

Quando si utilizza il 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 boot

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


1

Nel tuo IServece.cs aggiungi il seguente tag: BodyStyle = WebMessageBodyStyle.Bare

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

    List<personClass> Getperson(string id);

puoi anche spiegare perché BodyStyle può influire sul risultato?
MBH,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.