2010-06-11 9 views
37

अद्यतन 10/19/2010 मुझे पता है कि मैंने कुछ समय पहले इस प्रश्न से पूछा था, लेकिन इन उत्तरों में दिखाए गए कामकाज शायद ही संतोषजनक हैं, और यह अभी भी कई लोगों के लिए एक आम समस्या है। डब्ल्यूसीएफ बस लचीला नहीं है। मैंने डब्ल्यूसीएफ के बिना आरईएसटी सेवाओं को बनाने के लिए अपना खुद का खुला स्रोत सी # लाइब्रेरी शुरू की। कहा पुस्तकालय की जानकारी के लिए restcake.net या rest.codeplex.com देखें। अंत अद्यतनमैं जेसन.नेट का उपयोग करके, मेरी डब्लूसीएफ रेस्ट सर्विस (.NET 4) से जेसन को कैसे लौटा सकता हूं, बिना किसी स्ट्रिंग के उद्धरण में लपेटा जा सकता है?

अद्यतन 2012/08/02 ASP.NET Web API (पहले WCF वेब एपीआई, बाकी WCF के लिए प्रतिस्थापन) Json.NET डिफ़ॉल्ट रूप से उपयोग करता अंत अद्यतन

DataContractJsonSerializer संभालने में असमर्थ है कई परिदृश्य जो Json.Net ठीक से कॉन्फ़िगर किए जाने पर ठीक है (विशेष रूप से, चक्र)।

एक सेवा विधि एक विशिष्ट ऑब्जेक्ट प्रकार लौट सकते हैं या तो (इस मामले में एक DTO में) है, जो मामले में DataContractJsonSerializer उपयोग किया जाएगा, या मैं विधि हो सकता है एक स्ट्रिंग लौटने के लिए, और क्रमबद्धता करना अपने आप Json.Net साथ । समस्या यह है कि जब मैं किसी ऑब्जेक्ट के विपरीत एक जेसन स्ट्रिंग लौटाता हूं, क्लाइंट को भेजा गया जेसन उद्धरण में लपेटा जाता है।

का उपयोग DataContractJsonSerializer, एक विशिष्ट ऑब्जेक्ट प्रकार लौटने प्रतिक्रिया है:
{"Message":"Hello World"}

एक json स्ट्रिंग वापस जाने के लिए Json.Net का उपयोग करना, प्रतिक्रिया है:
"{\"Message\":\"Hello World\"}"

मैं क्लाइंट पर परिणाम() या JSON.parse() को eval करना नहीं चाहते हैं, जो मुझे करना होगा यदि जेसन एक स्ट्रिंग के रूप में वापस आ जाता है, उद्धरण में लपेटा जाता है। मुझे एहसास है कि व्यवहार सही है; यह सिर्फ वही नहीं है जो मैं चाहता/चाहती हूं। मुझे कच्चे जेसन की जरूरत है; व्यवहार जब सेवा विधि का रिटर्न प्रकार एक ऑब्जेक्ट होता है, स्ट्रिंग नहीं।

तो, मैं अपनी विधि को ऑब्जेक्ट प्रकार कैसे लौटा सकता हूं, लेकिन नहीं DataContractJsonSerializer का उपयोग करें? इसके बजाय मैं Json.Net serializer का उपयोग करने के लिए कैसे कह सकता हूं?

या, प्रतिक्रिया स्ट्रीम पर सीधे लिखने के लिए कोई रास्ता है? तो मैं सिर्फ कच्चे जेसन को वापस कर सकता हूं? रैपिंग उद्धरण के बिना?

यहाँ संदर्भ के लिए मेरी काल्पनिक उदाहरण है,:

[DataContract] 
public class SimpleMessage 
{ 
    [DataMember] 
    public string Message { get; set; } 
} 

[ServiceContract] 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
public class PersonService 
{ 
    // uses DataContractJsonSerializer 
    // returns {"Message":"Hello World"} 
    [WebGet(UriTemplate = "helloObject")] 
    public SimpleMessage SayHelloObject() 
    { 
     return new SimpleMessage("Hello World"); 
    } 

    // uses Json.Net serialization, to return a json string 
    // returns "{\"Message\":\"Hello World\"}" 
    [WebGet(UriTemplate = "helloString")] 
    public string SayHelloString() 
    { 
     SimpleMessage message = new SimpleMessage() { Message = "Hello World" }; 
     string json = JsonConvert.Serialize(message); 
     return json; 
    } 

    // I need a mix of the two. Return an object type, but use the Json.Net serializer. 
} 
+0

मुझे यकीन नहीं है कि मैं समझता हूं कि आप किसी भी धारावाहिकरण का उपयोग क्यों कर रहे हैं। यदि आप WCF सेवा में जेएसओएन के रूप में वस्तुओं को वापस करना चाहते हैं, तो आप अनुबंध में 'WebMessageFormat.Json' के रूप में प्रतिक्रिया प्रारूप को बस सेट कर सकते हैं। – Cody

+0

कोडी डेटा कंट्रैक्ट SUCKS.You महत्वपूर्ण मूल्य नहीं कर सकते हैं और तारीखें बिना किसी वापसी के खराब हो जाती हैं। इसके अलावा यह धीमा है लेकिन यह महत्वपूर्ण नहीं है – GorillaApe

उत्तर

36

मुझे अंत में इसका समाधान पता चला। यह वही नहीं है जो मैंने पसंद किया होगा (जो विशिष्ट ऑब्जेक्ट प्रकार को वापस करना होगा, और किसी भी तरह से डब्ल्यूसीएफ को डेटाकंट्रैक्टजसनसेरियलाइज़र की बजाय जेसननेट सीरियललाइज़र का उपयोग करने का निर्देश देगा), लेकिन यह बहुत अच्छा काम कर रहा है, और यह सरल और स्पष्ट है।

इस नए समाधान का उपयोग कर मेरी काल्पनिक उदाहरण का विस्तार:

[WebGet(UriTemplate = "hello")] 
public void SayHello() 
{ 
    SimpleMessage message = new SimpleMessage() {Message = "Hello World"}; 
    string json = JsonConvert.Serialize(message); 
    HttpContext.Current.Response.ContentType = "application/json; charset=utf-8"; 
    HttpContext.Current.Response.Write(json); 
} 

नोट void की वापसी प्रकार। हम कुछ भी वापस नहीं करते हैं, क्योंकि इसे DataContractJsonSerializer के साथ क्रमबद्ध किया जाएगा। इसके बजाय, मैं प्रतिक्रिया आउटपुट स्ट्रीम पर सीधे लिखता हूं। चूंकि रिटर्न टाइप शून्य है, प्रसंस्करण पाइपलाइन सामग्री प्रकार को "एप्लिकेशन/जेसन" के डिफ़ॉल्ट प्रकार पर सेट नहीं करती है, इसलिए मैंने इसे स्पष्ट रूप से सेट किया है।

क्योंकि इस HttpContext का उपयोग करता है, मैं इसे केवल, अगर आप अपने सेवा वर्ग पर [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] है काम करेंगे के बाद से है कि ASP.NET पाइप लाइन के माध्यम से जाने के लिए सेवा करने के लिए अनुरोध के लिए बाध्य करेगा अनुमान लगा रहा हूँ। एएसपीनेट संगतता के बिना, एचटीपी कॉन्टेक्स्ट उपलब्ध नहीं होगा, क्योंकि डब्ल्यूसीएफ होस्टिंग मेजबान अज्ञेयवादी होना चाहिए।

इस विधि का उपयोग करके, परिणाम जीईटी अनुरोधों के लिए फायरबग में सही दिखते हैं।सही सामग्री-प्रकार, सही सामग्री की लंबाई, और कच्चे जेसन, उद्धरण में लपेटा नहीं है। और, मुझे सीरियलाइजेशन मिल रहा है जिसे मैं जेसननेट का उपयोग करना चाहता हूं। दोनों ओर से लाभदायक।

मैं क्या बाधाएं मैं के बारे में में आ सकते हैं की 100% सकारात्मक नहीं कर रहा हूँ डी क्रमबद्धता, जब मेरे सेवा तरीकों इनपुट पैरामीटर के रूप में [DataContract] वस्तु प्रकार हैं। मुझे लगता है कि DataContractJsonSerializer का भी इसके लिए उपयोग किया जाएगा। जब मैं उस पर आऊंगा तो उस पुल को पार कर जाएगा ... अगर यह कोई समस्या पैदा करता है। यह मेरे सरल डीटीओ के साथ अब तक नहीं है।

अद्यतन ओलेग का उत्तर (UPDATE2 भाग) देखें। उन्होंने System.ServiceModel.Channels.Message को शून्य से सेवा विधि के वापसी प्रकार बदलता है, और नहीं बल्कि HttpContext.Current.Response.Write() का उपयोग करने से, वह उपयोग करता है:

return WebOperationContext.Current.CreateTextResponse (json, 
    "application/json; charset=utf-8", Encoding.UTF8); 

वास्तव में एक बेहतर समाधान है कौन सा। धन्यवाद ओलेग।

अद्यतन 2 इसे पूरा करने का एक और तरीका है। स्ट्रीम के लिए संदेश से अपनी सेवा की वापसी प्रकार बदलें, और वापसी इस:

WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8"; 
return new MemoryStream(System.Text.Encoding.UTF8.GetBytes(json)); 

मैं किसी भी विशिष्ट परीक्षण नहीं किया है, लेकिन यह संभव है कि इस तरीके कि संभावित डेटा की बड़ी मात्रा लौट सकता है के लिए एक बेहतर विकल्प होगा । मुझे नहीं पता कि यह गैर-बाइनरी डेटा के लिए महत्वपूर्ण है या नहीं। वैसे भी, एक विचार।

10

ऐसा नहीं है कि आप सही DataContractJsonSerializer नहीं का उपयोग मुझे लगता है। अजीब बात यह है कि: विधि के लिए आप ResponseFormat = ResponseFormat.Json विशेषता को परिभाषित नहीं करते हैं।

इसके अलावा यदि आप एक स्ट्रिंग में {"Message":"Hello World"} है और डीबगर में प्रदर्शित यह "{\"Message\":\"Hello World\"}" के रूप में प्रदर्शित किया जाएगा, तो वास्तव में आप जैसे string json = JsonConvert.Serialize(message); देखना (Json.Net)। तो मुझे ऐसा लगता है कि आपके पास दोनों मामलों में एक ही परिणाम हैं।

यह सत्यापित करने के लिए कि क्लाइंट सॉफ़्टवेयर का उपयोग परिणाम पढ़ें।अपने कोड में आप विधि SayHelloString() को परिभाषित: कुछ उदाहरण

JQuery ajax call to httpget webmethod (c#) not working

Can I return JSON from an .asmx Web Service if the ContentType is not JSON?

How do I build a JSON object to send to an AJAX WebService?

UPDATED देखें। इसका परिणाम एक स्ट्रिंग है। यदि आप विधि को कॉल करते हैं तो यह स्ट्रिंग एक और बार JSON क्रमबद्ध होगा। स्ट्रिंग {"Message":"Hello World"} स्ट्रिंग का JSON क्रमबद्धता एक उद्धृत स्ट्रिंग है (http://www.json.org/ किसी वस्तु के लिए परिभाषा नहीं, लेकिन एक स्ट्रिंग) या बिल्कुल "{\"Message\":\"Hello World\"}" स्ट्रिंग करें। तो सब कुछ आपकी वेब सेवा के दोनों तरीकों से सही है।

अद्यतन 2: मुझे खुशी है कि मेरे उत्तर के "अपडेट" भाग से मेरी नोक ने आपको डबल JSON क्रमबद्धता को बदलने में मदद की।

फिर भी मैं आपको डब्ल्यूसीएफ अवधारणा में अधिक रहने के लिए थोड़ा सा समाधान बदलने की सलाह दूंगा।

आप एक कस्टम अपने WCF विधि बेहतर लौटना चाहिए Message बजाय void WCF (http://msdn.microsoft.com/en-us/library/ms734675.aspx देखें) में वेब प्रतिक्रिया की एन्कोडिंग को लागू करना चाहते हैं: आप कारण के कर सकते हैं

[WebGet(UriTemplate = "hello")] 
public Message SayHello() 
{ 
    SimpleMessage message = new SimpleMessage() {Message = "Hello World"}; 
    string myResponseBody = JsonConvert.Serialize(message); 
    return WebOperationContext.Current.CreateTextResponse (myResponseBody, 
       "application/json; charset=utf-8", 
       Encoding.UTF8); 
} 

एक और संदेश formater का उपयोग करें: उदाहरण के लिए CreateStreamResponse (या कुछ अन्य http://msdn.microsoft.com/en-us/library/system.servicemodel.web.weboperationcontext_methods(v=VS.100).aspx देखें) CreateTextResponse के बजाय। आप (कुछ त्रुटि के मामले में उदाहरण के लिए) कुछ अतिरिक्त HTTP हेडर या HTTP स्थिति कोड स्थापित करने के लिए आप इस तरह के साथ ऐसा कर सकते हैं:

OutgoingWebResponseContext ctx = WebOperationContext.Current.OutgoingResponse; 
ctx.StatusCode = HttpStatusCode.BadRequest; 

अंत मैं एक टिप्पणी से मेरे सवाल दोहराने चाहते हैं पर: क्या आप समझा सकते हैं कि आप के बजाय Json.Net का उपयोग क्यों करना चाहते हैं? क्या यह प्रदर्शन सुधार है? क्या आपको DateTime जैसे कुछ डेटा प्रकारों के क्रमिकरण को DataContractJsonSerializer के रूप में लागू करने की आवश्यकता है? या Json.Net के अपने चयन का मुख्य कारण कुछ अन्य है?

+0

मेरे web.config में, मेरे में डिफ़ॉल्ट आउटपुट ResponseFormat = "Json" है, इसलिए मुझे इसे सेवा विधि पर विशेषता में निर्दिष्ट करने की आवश्यकता नहीं है। मैं DataContractJsonSerializer का सही ढंग से उपयोग कर रहा हूं, और यह एक मुद्दा नहीं है कि यह डीबगर में कैसे प्रदर्शित होता है। मैं इसे फायरबग या फिडलर में देख सकता हूं, और न केवल सटीक वर्णों को देख सकता हूं, बल्कि सामग्री की लंबाई भी देखता हूं, इसलिए मुझे पता है कि इसमें क्या शामिल है। यह दोनों मामलों में एक ही परिणाम नहीं है; मैंने मूल प्रश्न में वर्णित किया है। –

+0

समस्या यह है कि यदि आप http://www.jsonlint.com/ (JSON के निर्माता के एक साइट की साइट) पर जाते हैं तो आप सत्यापित कर सकते हैं कि '{" संदेश ":" हैलो वर्ल्ड "}' एक वैध JSON डेटा है, लेकिन '" {\ "संदेश \": \ "हैलो वर्ल्ड \"} "' नहीं है। Http://www.jsonlint.com में पेस्ट आज़माएं सटीक तार जो आप फिडलर/फायरबग में देखते हैं और आप देखेंगे कि आपके पास सही JSON है या नहीं। Http://www.json.org/ पर आपको JSON विनिर्देश मिलेगा। – Oleg

+0

मुझे एहसास है कि "{\" संदेश \ ": \" हैलो वर्ल्ड \ "}" मान्य नहीं है "कच्चे" जेसन। यह वैध जेसन है, जो एक स्ट्रिंग के रूप में पारित होता है, इसलिए यह उद्धरणों में लपेटा जाता है। इसे eval() या JSON.parse() में पारित किया जाना था, तो यह ठीक ठीक मूल्यांकन करेगा, क्योंकि यह * वैध जेसन है। लेकिन, यह न तो मेरा मुद्दा है, न ही मेरा सवाल है। –

संबंधित मुद्दे

 संबंधित मुद्दे