2013-01-04 51 views
7

मैंने इस पर जानकारी के लिए नेट को खराब कर दिया है, लेकिन अधिकांश परिणाम डब्ल्यूसीएफ सेवाओं या परिस्थितियों को बनाने के बारे में हैं जहां सेवा आपके नियंत्रण में है।डब्ल्यूसीएफ क्लाइंट मैं JSON प्रतिक्रिया से एक असंगत दिनांक प्रारूप को कैसे बेकार कर सकता हूं?

मैं एक विश्वसनीय जेएसओएन सेवा के लिए डब्ल्यूसीएफ क्लाइंट प्रॉक्सी का निर्माण कर रहा हूं जो मेरे नियंत्रण से बाहर है। मैं मूल सेवा नियंत्रण/डेटाकंट्रैक्ट पैटर्न का उपयोग कर रहा हूं, और ढांचे को जितना संभव हो उतना काम करने की कोशिश कर रहा हूं।

अधिकतर यह ठीक काम कर रहा है, लेकिन इस बाहरी सेवा से आने वाले सभी डेटाटाइम फ़ील्ड एक विशेष प्रारूप में हैं, उदा।

There was an error deserializing the object of type MyNamespace.SomeObject. DateTime content '2013/01/02 23:14:55 +0000' does not start with '/Date(' and end with ')/' as required for JSON.'.

मेरे datacontract है:

namespace Marshmallow.WebServices.ServiceModels 
{ 
    [DataContract] 
    public class SomeObject 
    { 
     [DataMember(Name = "details")] 
     public string Details { get; set; } 

     [DataMember(Name = "lastmodified")] 
     public DateTime LastModified { get; set; } 
    } 
} 

मेरे servicecontract है:

{"SomeObject": 
    {"details":"blue and round", "lastmodified":"2013/01/02 23:14:55 +0000"} 
} 

तो मैं कोई त्रुटि मिलती है

[ServiceContract] 
public interface ICoolExternalApi 
{ 
    [OperationContract] 
    [WebGet(UriTemplate = "/something.json", 
     ResponseFormat = WebMessageFormat.Json, 
     BodyStyle = WebMessageBodyStyle.Wrapped)] 
    [return: MessageParameter(Name = "SomeObject")] 
    SomeObject GetAccount(); 
} 

क्या मैं जानना चाहता है चाहता हूँ, मैं कुछ कोड कहाँ रख सकता हूँ ई परिभाषित करने के लिए कि कैसे डब्ल्यूसीएफ को अंतिम मॉड्यूलिज्ड फ़ील्ड को deserialize करना चाहिए (स्ट्रिंग से डेटटाइम ऑब्जेक्ट बनाना)?

या बेहतर अभी तक, परिभाषित करें कि मेरे सभी डेटाकंट्रैक्ट्स के लिए सभी डेटटाइम डेटामेम्बर को कैसे बेकार कर दिया जाए। मैं बहुत बार दोहराया कोड नहीं चाहता।

मैं कुछ तीसरे पक्ष के deserializer का सहारा लेना नहीं चाहता हूं और न ही मैं एक और deserialization विधि के माध्यम से सब कुछ डालना शुरू करना चाहता हूं, अगर यह टालने योग्य है।

+0

स्ट्रिंग के लिए Deserializing में सीमाएं हैं जो आपने नोट किया है। यह काम करेगा लेकिन सुरुचिपूर्ण से बहुत दूर है। एक IDispatchMessageInspector सेट अप करना थोड़ा और प्रयास है लेकिन क्लीनर होना चाहिए। –

+1

मुझे लगता है कि एक IDispatchMessageInspector का उपयोग करना वास्तव में सुरुचिपूर्ण नहीं है। ए) रेगेक्स धीमा है और बहुत पैमाने पर नहीं है। बी) यह पूरे जेसन बॉडी का एक अतिरिक्त पार्स है। सी) मुझे डेटाटाइम स्ट्रिंग को 'उस' प्रारूप में परिवर्तित करना होगा "\/दिनांक (12 9 72 9 308 9984-0800) \ /" जिसे डेटामेम्बर (डबल प्रोसेसिंग) को पॉप्युलेट करने के लिए फिर से पार्स किया जाएगा। डी) यह एक हैक है। निश्चित रूप से एक और डब्ल्यूसीएफ सुविधा होनी चाहिए जिसे मैं समझ नहीं पा रहा हूं (ऑनडिसेरियलाइजिंग या कुछ?) जो इन परिस्थितियों से निपटने के लिए डिज़ाइन किया गया है? –

उत्तर

1

अभी तक यह है सबसे अच्छा मैं के साथ आ गए हैं:

मैं एक आंतरिक स्ट्रिंग एक्सटेंशन विधि है:

internal static class DeserializationHelper 
{ 
    internal static DateTime GetDeserializedDateTime(this string @string) 
    { 
     if (string.IsNullOrEmpty(@string)) return default(DateTime); 
     //insert complex custom deserialization logic here 
     return DateTime.Parse(@string); 
    } 

} 

यह DataMember सेटअप है:

[DataMember(Name = "lastmodified")] 
internal string _LastModified 
{ 
    set { LastModified = value.GetDeserializedDateTime(); } 
    //getter is not needed for receiving data but WCF requires one 
    get { return default(string); } 
} 

public DateTime LastModified { get; private set; } 

यदि आप डेटा भेजने के लिए इस डेटाकंट्रैक्ट का उपयोग करना चाहते हैं (इसे एक लिखने योग्य संपत्ति बनाएं), तो आपको डेटटाइम एक्सटेंशन विधि लिखनी होगी (GetSerialized डेटस्ट्रिंग), सेटर्स/गेटर्स का विस्तार करें और निजी सदस्यों को go-betweens के रूप में पेश करें।

यह कट और पेस्ट की गंध करता है, और यह किसी भी डब्ल्यूसीएफ फ्रेमवर्क सुविधाओं का लाभ नहीं लेता है। बिल गेट्स क्या करेंगे?

2

दो बातें मैं के बारे में सोच सकते हैं:

  1. LastModified बदलें एक स्ट्रिंग होना करने के लिए और फिर एक Datetime करने के लिए इसे परिवर्तित ऑब्जेक्ट को स्वयं। इसका मतलब यह होगा कि आपके ऑब्जेक्ट पर उसी डेटा के लिए दो गुणों का खुलासा करना है।
  2. desisialization होने से पहले संदेश को अवरुद्ध करने के लिए एक IDispatchMessageInspector लिखें और regex का उपयोग कर कच्चे संदेश को मालिश करें। यह आपकी सेवा की सभी तिथियों के लिए एक स्टॉप समाधान की अनुमति देगा।
+0

आपके इनपुट के लिए धन्यवाद। 1) स्ट्रिंग संपत्ति को आंतरिक रखते हुए, अब तक मैं यही कर रहा हूं। इसके लिए प्रत्येक डेटटाइम डेटामेम्बर के लिए अतिरिक्त कोडिंग की आवश्यकता होती है, हालांकि, यह मेरे लिए बहुत खराब गंध करता है। 2) हालांकि यह काम करेगा, यह एक हैक की तरह लगता है, और ओवरहेड पेश करता है जो स्केलबिलिटी समझौता करेगा। –