【问题标题】:DataContractSerializer - Namespace issuesDataContractSerializer - 命名空间问题
【发布时间】:2013-11-29 12:47:04
【问题描述】:

我正在使用 HttpClient 将 xml 发布到休息服务。问题是服务需要命名空间前缀,而我无法使用 DataContractSerializer 实现。

预期的 xml:

<gto:createRequest xmlns:gto="http://www...com/sign">
    <userId></userId>
    <visibleDataContentType></visibleDataContentType>
    <visibleData></visibleData>
    <hiddenData></hiddenData>
    <expiryInSeconds></expiryInSeconds>
</gto:createRequest>

我正在序列化的对象:

namespace ABC
{
    [DataContract(Name = "createRequest", Namespace = "http://www...com/sign")]
    public class CreateRequest
    {
        [DataMember(Name = "userId")]
        public string UserId { get; set; }

        [DataMember(Name = "visibleDataContentType")]
        public string VisibleDataContentType { get; set; }

        [DataMember(Name = "visibleData")]
        public string VisibleData { get; set; }

        [DataMember(Name = "hiddenData")]
        public string HiddenData { get; set; }

        [DataMember(Name = "expiryInSeconds")]
        public int ExpiryInSeconds { get; set; }
    }
}

我无法获得前缀“gto: createRequest”,这是 DataContractSerializer 输出的内容:

<createRequest xmlns="http://www...com/sign" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
   <expiryInSeconds></expiryInSeconds>
   <hiddenData></hiddenData>
   <userId></userId>
   <visibleData></visibleData>
   <visibleDataContentType></visibleDataContentType>
</createRequest>

我尝试过旧的 XmlSerializer,但没有成功。有什么想法!?
更新:命名空间前缀不必是 gto: 但我必须在那里!

更新:Ondrej Svejdars 的输出回答服务器不接受:

<gto:createRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:gto="http://www.test.com/sign">
    <gto:expiryInSeconds>60</gto:expiryInSeconds>
    <gto:hiddenData>hidden</gto:hiddenData>
    <gto:userId>123456</gto:userId>
    <gto:visibleData>visible</gto:visibleData>
    <gto:visibleDataContentType>text/plain</gto:visibleDataContentType>
</gto:createRequest>

【问题讨论】:

  • 该服务仅在显式声明命名空间时才有效?这很奇怪。

标签: c# xml namespaces datacontractserializer


【解决方案1】:

[已编辑以匹配 gto:仅在顶部元素上]

您可以调整 xml 编写器:

public class XmlProxyWritter : XmlTextWriter {
  private string m_NS;
  public XmlProxyWritter(string ns, TextWriter w)
    : base(w) {
      m_NS = ns;
  }
  public XmlProxyWritter(string ns, Stream w, Encoding encoding)
    : base(w, encoding) {
      m_NS = ns;
  }
  public XmlProxyWritter(string ns, string filename, Encoding encoding)
    : base(filename, encoding) {
      m_NS = ns;
  }

  public override string LookupPrefix(string ns) {
    if (string.Compare(ns, m_NS, StringComparison.OrdinalIgnoreCase) == 0) {
      return "gto";
    }
    return base.LookupPrefix(ns);
  }

  public override void WriteStartElement(string prefix, string localName, string ns) {
    if (string.IsNullOrEmpty(prefix) && !string.IsNullOrEmpty(ns)) {
      prefix = LookupPrefix(ns);
    }
    base.WriteStartElement(prefix, localName, ns);
  }
}

商务舱:

[XmlRoot(ElementName = "createRequest", Namespace = "http://www.test.com/sign")]
public class CreateRequest {
  [XmlElement(ElementName="userId", Namespace = "")]
  public string UserId { get; set; }

  [XmlElement(ElementName = "visibleDataContentType", Namespace = "")]
  public string VisibleDataContentType { get; set; }

  [XmlElement(ElementName = "visibleData", Namespace = "")]
  public string VisibleData { get; set; }

  [XmlElement(ElementName = "hiddenData", Namespace = "")]
  public string HiddenData { get; set; }

  [XmlElement(ElementName = "expiryInSeconds", Namespace = "")]
  public int ExpiryInSeconds { get; set; }
}    

调用示例(http://www.test.com/sign 是 CreateRequest 的命名空间)

  string result;
  var serXml = new XmlSerializer(typeof(CreateRequest));

  using (var stream = new MemoryStream()) {
    using (var writer = new XmlProxyWritter("http://www.test.com/sign", stream, Encoding.UTF8)) {
      serXml.Serialize(writer, new CreateRequest {
        ExpiryInSeconds = 1,
        HiddenData = "my preasures",
        UserId = "Pepa"
      });
    }
    result = Encoding.UTF8.GetString(stream.ToArray());
  }

输出:

<?xml version="1.0" encoding="utf-8"?>
<gto:createRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:gto="http://www.test.com/sign">
  <userId>Pepa</userId>
  <hiddenData>my preasures</hiddenData>
  <expiryInSeconds>1</expiryInSeconds>
</gto:createRequest>

这对你有用(我希望),但感觉有点像黑客;也许这里正确的解决方案是“教”服务器正确的 xml 格式? :)

【讨论】:

  • 谢谢,但这会在所有元素上输出 gto: 并且服务器不接受 :-( (我已经用输出更新了问题)。
  • 是的,正如你所说,有点 hack yob :-) 更改服务器端会更好,但可惜我无法控制。
猜你喜欢
  • 2012-06-28
  • 1970-01-01
  • 2011-02-05
  • 2013-03-26
  • 2016-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多