2009-09-03 14 views
6

मैं एक सेवा WCF बाकी स्टार्टर किट का पूर्वावलोकन 2 का उपयोग करके बनाया है, लेकिन मैं कॉल में XML स्टाइल डेटा के आसपास गुजर के साथ कोई समस्या आई है। यहां मेरा अनुरोध ऑब्जेक्ट है:WCF बाकी स्टार्टर किट के साथ CDATA का उपयोग

[DataContract(Namespace = "")] 
public class ServiceRequest 
{ 
    [DataMember] 
    public string ContentText { get; set; } 
    [DataMember] 
    public string ApiKey { get; set; } 

} 

सबकुछ ठीक काम करता है जब तक आप वहां 'फेंक नहीं देते। क्या कोई सीडीएटीए या कुछ समान में ContentText प्रॉपर्टी को समाहित करने के लिए कोई है?

उत्तर

11

मार्क Gravell CDATA भाग serializing के लिए एक समाधान here है।

मैं भावी पीढ़ी के लिए यहाँ कोड की नकल की है।

अद्यतन: पिछले उदाहरण एक वैध स्कीमा उत्पन्न नहीं किया था, XmlSchemaProviderAttribute और साथ विधि उत्पन्न होगा "XS: स्ट्रिंग" जो स्वीकार किए जाते हैं जवाब में CDataWrapper की [more...]

using System; 
using System.IO; 
using System.Runtime.Serialization; 
using System.Xml; 
using System.Xml.Serialization; 
using System.ComponentModel; 

[XmlSchemaProvider("GenerateSchema")] 
public sealed class CDataWrapper : IXmlSerializable 
{ 
    // implicit to/from string 
    public static implicit operator string(CDataWrapper value) 
    { 
    return value == null ? null : value.Value; 
    } 

    public static implicit operator CDataWrapper(string value) 
    { 
    return value == null ? null : new CDataWrapper { Value = value }; 
    } 

    public System.Xml.Schema.XmlSchema GetSchema() 
    { 
    return null; 
    } 

    // return "xs:string" as the type in scheme generation 
    public static XmlQualifiedName GenerateSchema(XmlSchemaSet xs) 
    { 
     return XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String).QualifiedName; 
    } 

    // "" => <Node/> 
    // "Foo" => <Node><![CDATA[Foo]]></Node> 
    public void WriteXml(XmlWriter writer) 
    { 
    if (!string.IsNullOrEmpty(Value)) 
    { 
     writer.WriteCData(Value); 
    } 
    } 

    // <Node/> => "" 
    // <Node></Node> => "" 
    // <Node>Foo</Node> => "Foo" 
    // <Node><![CDATA[Foo]]></Node> => "Foo" 
    public void ReadXml(XmlReader reader) 
    { 
    if (reader.IsEmptyElement) 
    { 
     Value = ""; 
    } 
    else 
    { 
     reader.Read(); 

     switch (reader.NodeType) 
     { 
     case XmlNodeType.EndElement: 
      Value = ""; // empty after all... 
      break; 
     case XmlNodeType.Text: 
     case XmlNodeType.CDATA: 
      Value = reader.ReadContentAsString(); 
      break; 
     default: 
      throw new InvalidOperationException("Expected text/cdata"); 
     } 
    } 
    } 

    // underlying value 
    public string Value { get; set; } 
    public override string ToString() 
    { 
    return Value; 
    } 
} 

// example usage 
[DataContract(Namespace="http://myobjects/")] 
public sealed class MyType 
{ 
    public string SomeValue { get; set; } 
    [DataMember(Name = "SomeValue", EmitDefaultValue = false)] 
    private CDataWrapper SomeValueCData 
    { 
    get { return SomeValue; } 
    set { SomeValue = value; } 
    } 

    public string EmptyTest { get; set; } 
    [DataMember(Name = "EmptyTest", EmitDefaultValue = false)] 
    private CDataWrapper EmptyTestCData 
    { 
    get { return EmptyTest; } 
    set { EmptyTest = value; } 
    } 

    public string NullTest { get; set; } 
    [DataMember(Name = "NullTest", EmitDefaultValue = false)] 
    private CDataWrapper NullTestCData 
    { 
    get { return NullTest ; } 
    set { NullTest = value; } 
    } 
} 

// test rig 
static class Program 
{ 
    static void Main() 
    { 
    DataContractSerializer dcs = new DataContractSerializer(typeof(MyType)); 

    StringWriter writer = new StringWriter(); 
    using (XmlWriter xw = XmlWriter.Create(writer)) 
    { 
     MyType foo = new MyType 
     { 
     SomeValue = @"&<t\d", 
     NullTest = null, 
     EmptyTest = "" 
     }; 

     ShowObject("Original", foo); 

     dcs.WriteObject(xw, foo); 
     xw.Close(); 
    } 

    string xml = writer.ToString(); 
    ShowObject("Xml", xml); 

    StringReader reader = new StringReader(xml); 
    using (XmlReader xr = XmlReader.Create(reader)) 
    { 
     MyType bar = (MyType) dcs.ReadObject(xr); 
     ShowObject("Recreated", bar); 
    } 
    } 

    static void ShowObject(string caption, object obj) 
    { 
    Console.WriteLine(); 
    Console.WriteLine("** {0} **", caption); 
    Console.WriteLine(); 

    if (obj == null) 
    { 
     Console.WriteLine("(null)"); 
    } 
    else if (obj is string) 
    { 
     Console.WriteLine((string)obj); 
    } 
    else 
    { 
     foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)) 
     { 
     Console.WriteLine("{0}:\t{1}", prop.Name, prop.GetValue(obj) ?? "(null)"); 
     } 
    } 
    } 
} 
3

वीबी रूपांतरण काम करता है:

Imports System 
Imports System.IO 
Imports System.Runtime.Serialization 
Imports System.Xml 
Imports System.Xml.Schema 
Imports System.Xml.Serialization 
Imports System.ComponentModel 

Public Class CDataWrapper 
    Implements IXmlSerializable 

    'underlying value 
    Public Property Value As String 

    'Implicit to/from string 
    Public Shared Widening Operator CType(ByVal value As CDataWrapper) As String 
     If value Is Nothing Then 
      Return Nothing 
     Else 
      Return value.Value 
     End If 
    End Operator 

    Public Shared Widening Operator CType(value As String) As CDataWrapper 
     If value Is Nothing Then 
      Return Nothing 
     Else 
      Return New CDataWrapper() With {.Value = value} 
     End If 
    End Operator 


    Public Function GetSchema() As XmlSchema Implements IXmlSerializable.GetSchema 
     Return Nothing 
    End Function 

    ' <Node/> => "" 
    ' <Node></Node> => "" 
    ' <Node>Foo</Node> => "Foo" 
    ' <Node><![CDATA[Foo]]></Node> => "Foo" 
    Public Sub ReadXml(reader As XmlReader) Implements IXmlSerializable.ReadXml 
     If reader.IsEmptyElement Then 
      Me.Value = "" 
     Else 
      reader.Read() 

      Select Case reader.NodeType 
       Case XmlNodeType.EndElement 
        Me.Value = "" ' empty after all... 
       Case XmlNodeType.Text, XmlNodeType.CDATA 
        Me.Value = reader.ReadContentAsString() 
       Case Else 
        Throw New InvalidOperationException("Expected text/cdata") 
      End Select 
     End If 
    End Sub 

    ' "" => <Node/> 
    ' "Foo" => <Node><![CDATA[Foo]]></Node> 
    Public Sub WriteXml(writer As XmlWriter) Implements IXmlSerializable.WriteXml 
     If Not String.IsNullOrEmpty(Me.Value) Then 
      writer.WriteCData(Me.Value) 
     End If 
    End Sub 

    Public Overrides Function ToString() As String 
     Return Me.Value 
    End Function 
End Class 
+0

अच्छा सामान। धन्यवाद केविन! –

+0

उपर्युक्त कोड सीडीटा के बाद गुणों को पार्स करना बंद कर देता है। यह एक समस्या है जब आप xml में एक से अधिक तत्वों की अपेक्षा करते हैं। ReadXml में और टैग के अंत में लापता reader.Read() जोड़ने से इस समस्या का समाधान कर। – Beejee

3

ऊपर कोड इस तथ्य को याद कर रहा है कि आपको इसे पढ़ने के बाद सामग्री को पीछे छोड़ना होगा। तो यह वर्ग जो खड़ा है वह संग्रह के साथ काम नहीं करेगा।

यह निम्नलिखित को बदलें, और अब आप CDataWrapper का संग्रह कर सकते हैं।

Value = reader.ReadContentAsString(); 
reader.Read(); 
0

हालांकि यह एक पुरानी पोस्ट है, यहां मेरी 2 ¢ है। मैंने डेटा सदस्य को XmlElement के रूप में परिभाषित करके इस समस्या को संबोधित किया।

[DataMember(Name = "MyCData")] 
     public XmlElement MyCDataField { get; set; } 
संबंधित मुद्दे