का उपयोग कर डब्ल्यूसीएफ सेवा में पॉलीमोर्फिक प्रकारों को संरक्षित करना मेरे पास एक वेब एचटीएफबी सेवा का उपयोग कर सी # डब्ल्यूसीएफ सेवा है जो जेएसओएन प्रारूप में डेटा प्राप्त और वापस कर देगी। भेजने/प्राप्त करने के लिए डेटा को पॉलिमॉर्फिक प्रकार का उपयोग करने की आवश्यकता होती है ताकि विभिन्न प्रकार के डेटा को उसी "डेटा पैकेट" में आदान-प्रदान किया जा सके। मैं निम्न डेटा मॉडल है:JSON
[DataContract]
public class DataPacket
{
[DataMember]
public List<DataEvent> DataEvents { get; set; }
}
[DataContract]
[KnownType(typeof(IntEvent))]
[KnownType(typeof(BoolEvent))]
public class DataEvent
{
[DataMember]
public ulong Id { get; set; }
[DataMember]
public DateTime Timestamp { get; set; }
public override string ToString()
{
return string.Format("DataEvent: {0}, {1}", Id, Timestamp);
}
}
[DataContract]
public class IntEvent : DataEvent
{
[DataMember]
public int Value { get; set; }
public override string ToString()
{
return string.Format("IntEvent: {0}, {1}, {2}", Id, Timestamp, Value);
}
}
[DataContract]
public class BoolEvent : DataEvent
{
[DataMember]
public bool Value { get; set; }
public override string ToString()
{
return string.Format("BoolEvent: {0}, {1}, {2}", Id, Timestamp, Value);
}
}
मेरी सेवा भेज देंगे, उप-प्रकार की घटनाओं (IntEvent, BoolEvent आदि) एक भी डाटा पैकेट में प्राप्त/इस प्रकार है:
[ServiceContract]
public interface IDataService
{
[OperationContract]
[WebGet(UriTemplate = "GetExampleDataEvents")]
DataPacket GetExampleDataEvents();
[OperationContract]
[WebInvoke(UriTemplate = "SubmitDataEvents", RequestFormat = WebMessageFormat.Json)]
void SubmitDataEvents(DataPacket dataPacket);
}
public class DataService : IDataService
{
public DataPacket GetExampleDataEvents()
{
return new DataPacket {
DataEvents = new List<DataEvent>
{
new IntEvent { Id = 12345, Timestamp = DateTime.Now, Value = 5 },
new BoolEvent { Id = 45678, Timestamp = DateTime.Now, Value = true }
}
};
}
public void SubmitDataEvents(DataPacket dataPacket)
{
int i = dataPacket.DataEvents.Count; //dataPacket contains 2 events, but both are type DataEvent instead of IntEvent and BoolEvent
IntEvent intEvent = dataPacket.DataEvents[0] as IntEvent;
Console.WriteLine(intEvent.Value); //null pointer as intEvent is null since the cast failed
}
}
जब मैं मेरे पैकेट को SubmitDataEvents
विधि पर सबमिट करें, हालांकि मुझे DataEvent
प्रकार मिलते हैं और उन्हें InvalidCastException
में परिणामों के आधार पर वापस अपने मूल प्रकार (केवल परीक्षण उद्देश्यों के लिए) कास्ट करने का प्रयास करते हैं। मेरे पैकेट है: लंबे समय तक इस पद के लिए
POST http://localhost:4965/DataService.svc/SubmitDataEvents HTTP/1.1
User-Agent: Fiddler
Host: localhost:4965
Content-Type: text/json
Content-Length: 340
{
"DataEvents": [{
"__type": "IntEvent:#WcfTest.Data",
"Id": 12345,
"Timestamp": "\/Date(1324905383689+0000)\/",
"Value": 5
}, {
"__type": "BoolEvent:#WcfTest.Data",
"Id": 45678,
"Timestamp": "\/Date(1324905383689+0000)\/",
"Value": true
}]
}
क्षमा याचना, लेकिन वहाँ कुछ भी मैं प्रत्येक वस्तु के आधार प्रकार संरक्षित करने के लिए कर सकते हैं? मैंने सोचा कि JSON के लिए संकेत संकेत जोड़ना और ज्ञात टाइप प्रकार DataEvent
पर मुझे प्रकारों को संरक्षित करने की अनुमति होगी - लेकिन ऐसा लगता है कि यह काम नहीं करता है।
संपादित: यदि मैं अनुरोध SubmitDataEvents
को XML स्वरूप में (Content-Type: text/xml
बजाय text/json
के साथ) भेजने तो List<DataEvent> DataEvents
सुपर प्रकार के बजाय उप-प्रकारों को शामिल करता है। जैसे ही मैंने text/json
पर अनुरोध सेट किया है और उपरोक्त पैकेट भेज दिया है, तो मुझे केवल सुपर-टाइप मिलता है और मैं उन्हें उप-प्रकार में नहीं डाल सकता। मेरे एक्सएमएल अनुरोध शरीर है:
<ArrayOfDataEvent xmlns="http://schemas.datacontract.org/2004/07/WcfTest.Data">
<DataEvent i:type="IntEvent" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Id>12345</Id>
<Timestamp>1999-05-31T11:20:00</Timestamp>
<Value>5</Value>
</DataEvent>
<DataEvent i:type="BoolEvent" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Id>56789</Id>
<Timestamp>1999-05-31T11:20:00</Timestamp>
<Value>true</Value>
</DataEvent>
</ArrayOfDataEvent>
संपादित 2: नीचे पावेल की टिप्पणी के बाद अपडेट किया गया सेवा विवरण। Fiddler2 में JSON पैकेट भेजते समय यह अभी भी काम नहीं करता है। मुझे List
IntEvent
और BoolEvent
के बजाय DataEvent
मिला है।
संपादित करें 3: जैसा कि पावेल ने सुझाव दिया है, यहां System.ServiceModel.OperationContext.Current.RequestContext.RequestMessage.ToString()
से आउटपुट है। मुझे ठीक लग रहा है।
<root type="object">
<DataEvents type="array">
<item type="object">
<__type type="string">IntEvent:#WcfTest.Data</__type>
<Id type="number">12345</Id>
<Timestamp type="string">/Date(1324905383689+0000)/</Timestamp>
<Value type="number">5</Value>
</item>
<item type="object">
<__type type="string">BoolEvent:#WcfTest.Data</__type>
<Id type="number">45678</Id>
<Timestamp type="string">/Date(1324905383689+0000)/</Timestamp>
<Value type="boolean">true</Value>
</item>
</DataEvents>
</root>
जब पैकेट के अक्रमांकन अनुरेखण, मैं पता लगाने में निम्न संदेश मिलता है:
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Verbose">
<TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.Runtime.Serialization.ElementIgnored.aspx</TraceIdentifier>
<Description>An unrecognized element was encountered in the XML during deserialization which was ignored.</Description>
<AppDomain>1c7ccc3b-4-129695001952729398</AppDomain>
<ExtendedData xmlns="http://schemas.microsoft.com/2006/08/ServiceModel/StringTraceRecord">
<Element>:__type</Element>
</ExtendedData>
</TraceRecord>
यह संदेश दोहराया है (दो बार __type
तत्व के रूप में और दो बार Value
साथ साथ) 4 बार। ऐसा लगता है कि टाइपिंग जानकारी को अनदेखा किया जा रहा है, तो Value
तत्वों को अनदेखा कर दिया गया है क्योंकि IntEvent
/BoolEvent
के बजाय पैकेट को DataEvent
पर deserialized किया गया है।
वाह ... आपकी समस्या को जानकर खुशी हुई है।हालांकि, स्वरूपित जेएसओएन ने मेरे लिए ठीक काम किया है, मैंने हमेशा इसे फिडलर को कॉपी-पेस्ट किया है और इसमें कोई समस्या नहीं है। मुझे विश्वास है कि या तो आपने .NET ढांचे के लिए सभी अद्यतन स्थापित नहीं किए हैं, या नवीनतम संस्करण में व्हाइटस्पेस वर्ण प्रसंस्करण से संबंधित एक अजीब बग है। मैं पूरी तरह से शर्मिंदा हूँ। –
बिल्कुल शर्मिंदा मत हो, मैं आपकी सहायता के बिना कभी नहीं पाया होगा। आपके द्वारा पता चला एकमात्र तरीका डब्ल्यूसीएफ स्रोत कोड को डीबग करके था जिसे आपने ऊपर पोस्ट किया था। मैंने देखा कि 'ऑफ़सेट' के लिए मान हमेशा बहुत कम था और यह नोटिस हुआ कि संदेश बफर में '\ r' और' \ n' वर्णों को शामिल करना ऑफसेट गणना को किसी भी तरह से फेंक रहा था। मैं यह देखने के लिए एक और सवाल पोस्ट कर सकता हूं कि क्या कोई जानता है कि व्हाइटस्पेस पार्सिंग में हस्तक्षेप क्यों करता है, क्योंकि मुझे इसमें शामिल होने की लचीलापन चाहिए या नहीं। –
ओह, यह 'शर्मिंदा' के बजाय 'भ्रमित' होना चाहिए था :)। वैसे, मुझे इसी तरह के मुद्दे का विवरण मिला है [इस आलेख में] (http://blog.js-development.com/2010/05/n-will-break-your-json-jquery-wcf.html)। –