【问题标题】:SOAP WCF: Prevent deserialization to private fieldsSOAP WCF:防止反序列化到私有字段
【发布时间】:2016-03-29 14:04:56
【问题描述】:

我正在尝试针对 WCF 从 SoapUI 执行 SOAP 调用,并且在反序列化 XML 时,它正尝试反序列化为私有字段。为什么会发生这种情况,我该如何解决?代码如下:

我使用标准 XSD.exe 从 XSD 文件生成 POCO 类,结果如下所示:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.81.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://iec.ch/TC57/2011/MeterConfig#")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://iec.ch/TC57/2011/MeterConfig#", IsNullable = false)]
public partial class MeterConfig
{

    private ComFunction[] comFunctionField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("ComFunction")]
    public ComFunction[] ComFunction
    {
        get { return this.comFunctionField; }
        set { this.comFunctionField = value; }
    }
}

我有一个 WCF SOAP 端点,如下所示:

[ServiceContract]
public class MyApi
{
    [OperationContract]
    public void CreateMeterConfig2(MeterConfig Payload)
    {
        //do nothing
    }
}

我有一个 SoapUI 测试项目,我在其中提供以下 XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:CreateMeterConfig2>
         <tem:Payload>

         </tem:Payload>
      </tem:CreateMeterConfig2>
   </soapenv:Body>
</soapenv:Envelope>

我得到的错误是:

Expecting element 'comFunctionField'

或全部:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <s:Fault>
         <faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:DeserializationFailed</faultcode>
         <faultstring xml:lang="en-ZA">The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:Payload. The InnerException message was 'Error in line 13 position 24. 'EndElement' 'Payload' from namespace 'http://tempuri.org/' is not expected. Expecting element 'comFunctionField'.'.  Please see InnerException for more details.</faultstring>
      </s:Fault>
   </s:Body>
</s:Envelope>

【问题讨论】:

    标签: c# xml wcf soap


    【解决方案1】:

    您的问题是您自动生成了一个标有XmlSerializer-specific attributes 的类型,但使用的是uses DataContractSerializer by default 的WCF。当DataContractSerializer 尝试序列化标有[SerializableAttribute] 但没有data contract attributes 的类型时,它会推断出类似于BinaryFormatter 工作方式的协定,即应该序列化公共和私有字段,而不是属性。 (更多信息请见Types Supported by the Data Contract Serializer。)

    要解决此问题,您可以:

    1. 通过将 [XmlSerializerFormatAttribute] 应用于您的服务,将 WCF 配置为使用 XmlSerializer。为此,请参阅 How to change Wcf to use a different serializer?Using the XmlSerializer Class,例如:

      [ServiceContract]
      [XmlSerializerFormat]
      public class MyApi
      {
          [OperationContract]
          public void CreateMeterConfig2(MeterConfig Payload)
          {
              //do nothing
          }
      }
      
    2. 使用svcutil.exe 而不是xsd.exe,使用数据协定属性而不是XmlSerializer 属性从您的XSD 自动生成您的类。为此,请参阅 Generate DataContract from XSDServiceModel Metadata Utility Tool (Svcutil.exe)

      请注意,DataContractSerializerXmlSerializer 相比有一些限制。例如,它不允许将属性选择性地序列化为 XML 属性而不是元素。有关更多信息,请参阅 XML Serialisation - When To Use DataContractSerializer / Binary / XMLSerialiserData Contract Serializer - How to omit the outer element of a collection。如果您的 XSD 与这些限制不兼容,您将需要使用 XmlSerializer

    【讨论】:

    • 一个非常彻底的答案,谢谢。我已经添加了 [XmlSerializerFormatAttribute] 来解决问题。
    猜你喜欢
    • 2011-01-08
    • 1970-01-01
    • 2014-10-29
    • 2011-09-19
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 2015-01-29
    • 2014-04-13
    相关资源
    最近更新 更多