将CDATA与WCF REST入门工具包一起使用

Joe*_*ley 6 c# rest wcf

我使用WCF REST入门套件的预览2构建了一个服务,但是我遇到了在调用中传递XML样式数据的问题.这是我的请求对象:

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

}
Run Code Online (Sandbox Code Playgroud)

一切正常,直到你扔进那里.有没有将ContentText属性封装在CDATA或类似的东西中?

Dar*_*ler 12

Marc Gravell 在此处提供了一个用于序列化CDATA部分的解决方案.

我在这里复制了代码以供后代使用.

更新:前面的示例没有生成有效的模式,XmlSchemaProviderAttribute和附带的方法将生成"xs:string",它可以工作[更多...]

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)");
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)