c# - 将 CDATA 与 WCF REST 初学者工具包一起使用

标签 c# wcf rest

我有一个使用 WCF REST 初学者工具包的预览版 2 构建的服务,但我遇到了在调用中传递 XML 样式数据的问题。这是我的请求对象:

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

}

一切正常,直到你把 '' 扔进去。是否可以将 ContentText 属性封装在 CDATA 或类似的东西中?

最佳答案

Marc Gravell 有一个解决方案 here用于序列化 CDATA 部分。

我已将代码复制到此处以供后代使用。

更新:前面的示例没有生成有效的架构,XmlSchemaProviderAttribute 和随附的方法将生成有效的“xs:string”[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)");
      }
    }
  }
}

关于c# - 将 CDATA 与 WCF REST 初学者工具包一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1374062/

相关文章:

c# - 以非对称方式合并两个 Dictionary<string, string>

c# - .NET 的 GUID 结构

c# - 如何在 WCF 客户端中同时提供用户名和客户端证书(此示例为何有效)?

c# - WCF-C#服务应连续发送结果

javascript - 参数更改 GET 请求后 Angular 重新获取数据

c# - 网络服务中的接口(interface)

c# - FsCheck:如何生成依赖于其他测试数据的测试数据?

wcf - 帮助 .NET 开发人员使用 Coldfusion 使用 WCF 服务

node.js - 在 Node.js 中实现 RESTful API

rest - 使用 REST 实现长时间运行的搜索的最佳实践