2010-01-18 34 views
211

Tôi đang cố trả lại một số JSON từ một dịch vụ WCF. Dịch vụ này chỉ trả về một số nội dung từ cơ sở dữ liệu của tôi. Tôi có thể lấy dữ liệu. Tuy nhiên, tôi lo ngại về định dạng JSON của tôi. Hiện tại, JSON được trả lại được định dạng như sau:Làm cách nào để trả lại JSON sạch từ một Dịch vụ WCF?

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

Thực tế, tôi muốn JSON của tôi được định dạng rõ ràng nhất có thể. Tôi tin rằng (tôi có thể không chính xác), rằng cùng một tập hợp các kết quả, được biểu thị bằng JSON rõ ràng, trông giống như vậy:

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

Tôi không biết "d" xuất phát từ đâu. Tôi cũng không biết tại sao các ký tự thoát được chèn vào. thực thể của tôi trông giống như sau:

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

Các dịch vụ đó là trách nhiệm trả lại nội dung được định nghĩa là:

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

Làm thế nào để trở về “làm sạch” JSON từ một dịch vụ WCF? Cảm ơn bạn!

+0

SOAP nên trở về XML. Bạn có thể sử dụng một điểm cuối REST để trả về JSON. Hãy xem http://stackoverflow.com/questions/186631/rest-soap-endpoints-for-a-wcf-service/186695#186695 –

+4

Nhân tiện, nếu có ai khác gặp phải điều này và tự hỏi tại sao "d" tài sản là có, nó có để vá một [lỗ hổng JSON] (http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/). Loại bỏ nó làm cho bạn dễ bị tổn thương một lần nữa. – Alex

+4

@Alex - Lỗ hổng đó phụ thuộc vào việc xác định lại đối tượng mảng, không còn khả thi trong các trình duyệt hiện đại nữa. Xem http://stackoverflow.com/questions/16289894/is-json-hijacking-still-an-issue-in-modern-browsers – Cheeso

Trả lời

195

Thay đổi loại trả về của GetResults thành List<Person>.
Loại bỏ mã mà bạn sử dụng để tuần tự hóa Danh sách thành chuỗi json - WCF thực hiện việc này cho bạn một cách tự động.

Sử dụng định nghĩa của bạn cho lớp Person, mã này làm việc cho tôi:

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

kết quả:

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

(Tất cả trên cùng một dòng)

Tôi cũng sử dụng thuộc tính này trên phương thức:

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

WebInvoke với Method = "GET" giống như WebGet, nhưng vì một số phương thức của tôi là POST, tôi sử dụng tất cả WebInvoke để nhất quán.

UriTemplate đặt URL nơi phương thức khả dụng. Vì vậy, tôi có thể làm một GET trên http://myserver/myvdir/JsonService.svc/players và nó chỉ hoạt động.

Ngoài ra, hãy kiểm tra IIRF hoặc một trình ghi đè URL khác để loại bỏ tệp .svc trong URI.

+0

Cheeso - Tôi đã thử phương pháp này trước khi đăng câu hỏi này. Khi tôi sử dụng cách tiếp cận này, tôi nhận được một lỗi nói rằng "Điểm cuối sử dụng 'UriTemplate' không thể được sử dụng với 'System.ServiceModel.Description.WebScriptEnablingBehavior'." Tôi đang làm gì sai? Cảm ơn bạn! – user208662

+26

sử dụng thay vì trong tệp .config của bạn. – Cheeso

+0

Tôi nhận được lỗi "điểm cuối sử dụng ..." ở trên nhưng không có trong web.config của tôi ở mọi nơi. nơi nào tôi đặt ? – MGOwen

87

Nếu bạn muốn thoải mái json mà không thuộc tính hardcoding vào các lớp dịch vụ của bạn,

sử dụng <webHttp defaultOutgoingResponseFormat="Json"/> trong cấu hình hành vi của bạn

1

Khi bạn đang sử dụng GET Phương pháp hợp đồng phải là cái này.

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

với điều này chúng ta có một json mà không có tham số khởi động

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

5

tôi phải đối mặt với cùng một vấn đề, và giải quyết nó bằng cách thay đổi giá trị bodystyle attribut để "WebMessageBodyStyle .Bare ":

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

Đối tượng được trả về sẽ không còn được bọc nữa ped.

0

Trong IServece.cs bạn thêm thẻ sau: bodystyle = WebMessageBodyStyle.Bare

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

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

bạn cũng có thể giải thích tại sao BodyStyle có thể ảnh hưởng đến kết quả không? – MBH

Các vấn đề liên quan