Using CDATA with WCF REST starter kits

后端 未结 4 1140
深忆病人
深忆病人 2020-12-16 06:16

I have a service built using Preview 2 of the WCF REST starter kit, but I\'ve run into an issue with passing around XML-styled data in the calls. Here\'s my request object:<

相关标签:
4条回答
  • 2020-12-16 06:23

    Although this is an older post here are my 2¢. I addressed this issue by defining the data member as XmlElement.

     [DataMember(Name = "MyCData")]
            public XmlElement MyCDataField { get; set; }
    
    0 讨论(0)
  • 2020-12-16 06:28

    Above code is missing the fact that you must go past the content after you have read it. So this class as it stands won't work with a collection.

    Change it to the following, and you can now hold Collections of CDataWrapper.

    Value = reader.ReadContentAsString(); 
    reader.Read();
    
    0 讨论(0)
  • 2020-12-16 06:29

    VB conversion of the CDataWrapper in the accepted answer:

    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)
  • 2020-12-16 06:34

    Marc Gravell has a solution here for serializing CDATA sections.

    I have copied the code here for posterity.

    updated: the previous example did not generate a valid schema, the XmlSchemaProviderAttribute and accompanying method will generate "xs:string" which works [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)");
          }
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题