Bagaimana cara mengembalikan JSON bersih dari Layanan WCF?

233

Saya mencoba mengembalikan beberapa JSON dari layanan WCF. Layanan ini hanya mengembalikan beberapa konten dari basis data saya. Saya bisa mendapatkan datanya. Namun, saya khawatir tentang format JSON saya. Saat ini, JSON yang akan dikembalikan diformat seperti ini:

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

Pada kenyataannya, saya ingin JSON saya diformat sebersih mungkin. Saya percaya (saya mungkin salah), bahwa kumpulan hasil yang sama, diwakili dalam JSON bersih, akan terlihat seperti ini:

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

Saya tidak tahu dari mana "d" berasal. Saya juga tidak tahu mengapa karakter escape dimasukkan. Entitas saya terlihat seperti berikut:

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

Layanan yang bertanggung jawab untuk mengembalikan konten didefinisikan sebagai:

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

Bagaimana cara mengembalikan JSON "bersih" dari layanan WCF? Terima kasih!

pengguna208662
sumber
SOAP harus mengembalikan XML. Anda dapat menggunakan titik akhir REST untuk mengembalikan JSON. Lihatlah stackoverflow.com/questions/186631/…
Akira Yamamoto
4
By the way, jika orang lain menemukan ini dan bertanya-tanya mengapa properti "d" ada di sana, itu ada di sana untuk menambal kerentanan JSON . Menghapusnya membuat Anda rentan lagi.
Alex
4
@Alex - Kerentanan yang bergantung pada mendefinisikan ulang objek Array, yang tidak lagi mungkin di browser modern. Lihat stackoverflow.com/questions/16289894/…
Cheeso
Itu bagus. :) Setengah jawaban saya masih benar - itu ada untuk menambal kerentanan itu.
Alex

Jawaban:

213

Ubah tipe pengembalian GetResults Anda menjadi List<Person>.
Hilangkan kode yang Anda gunakan untuk membuat serial daftar untuk string json - WCF melakukan ini untuk Anda secara otomatis.

Menggunakan definisi Anda untuk kelas Person, kode ini berfungsi untuk saya:

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

hasil:

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

(Semua dalam satu baris)

Saya juga menggunakan atribut ini pada metode:

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

WebInvoke dengan Metode = "GET" sama dengan WebGet, tetapi karena beberapa metode saya POST, saya menggunakan semua WebInvoke untuk konsistensi.

UriTemplate menetapkan URL tempat metode ini tersedia. Jadi saya bisa melakukan GET http://myserver/myvdir/JsonService.svc/playersdan berfungsi.

Periksa juga IIRF atau penulis ulang URL lain untuk menyingkirkan .svc di URI.

Cheeso
sumber
Cheeso - Saya mencoba pendekatan ini sebelum saya memposting pertanyaan ini. Ketika saya menggunakan pendekatan ini, saya mendapatkan kesalahan yang mengatakan "Titik akhir menggunakan 'UriTemplate' tidak dapat digunakan dengan 'System.ServiceModel.Description.WebScriptEnablingBehavior'." Apa yang saya lakukan salah? Terima kasih!
user208662
28
gunakan <webHttp /> alih-alih <webScriptEnablingBehavior /> dalam file .config Anda.
Cheeso
9
OK, saya mengganti <enableWebScript /> dengan <webHttp /> dan itu berhasil.
MGOwen
3
MGowen - FYI, taruhan terbaik ketika mengajukan pertanyaan baru adalah ... membuka pertanyaan baru, daripada memposting pertanyaan sebagai komentar untuk jawaban lama.
Cheeso
5
Favre melihat apa yang Anda lakukan di sana.
ruffin
93

Jika Anda ingin json yang bagus tanpa atribut hardcoding ke dalam kelas layanan Anda,

gunakan <webHttp defaultOutgoingResponseFormat="Json"/>dalam konfigurasi perilaku Anda

JeremyWeir
sumber
8

Saya menghadapi masalah yang sama, dan menyelesaikannya dengan mengubah nilai atribut BodyStyle menjadi "WebMessageBodyStyle.Bare":

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

Objek yang dikembalikan tidak akan lagi dibungkus.

KhalilG
sumber
1

Ketika Anda menggunakan Metode GET, kontrak harus seperti ini.

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

dengan ini kita memiliki json tanpa parameter boot

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

alduar
sumber
1

Di IServece.cs Anda tambahkan tag berikut: BodyStyle = WebMessageBodyStyle.Bare

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

    List<personClass> Getperson(string id);
Osama Ibrahim
sumber
dapatkah Anda menjelaskan mengapa BodyStyle dapat memengaruhi hasilnya?
MBH