SOAP WCF:防止反序列化为专用字段



我正试图从SoapUI针对WCF执行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>

您的问题是,您自动生成了一个标记有XmlSerializer特定属性的类型,但使用的是默认使用DataContractSerializer的WCF。当DataContractSerializer试图序列化一个标记有[SerializableAttribute]但没有数据协定属性的类型时,它会推断出一个类似于BinaryFormatter工作方式的协定,即应该序列化公共和私有字段,而不是属性。(有关更多信息,请参阅数据协定序列化程序支持的类型。)

要解决这个问题,您可以:

  1. 通过将[XmlSerializerFormatAttribute]应用于您的服务,将WCF配置为使用XmlSerializer。要执行此操作,请参阅如何更改Wcf以使用不同的序列化程序?和使用XmlSerializer类,例如:

    [ServiceContract]
    [XmlSerializerFormat]
    public class MyApi
    {
        [OperationContract]
        public void CreateMeterConfig2(MeterConfig Payload)
        {
            //do nothing
        }
    }
    
  2. 通过使用svcutil.exe而不是xsd.exe,从具有数据协定属性而不是XmlSerializer属性的XSD中自动生成类。为此,请参阅从XSD和ServiceModel元数据实用工具(Svcutil.exe)生成DataContract

    注意,与XmlSerializer相比,DataContractSerializer具有一些限制。例如,它不允许将属性选择性地序列化为XML属性而不是元素。有关更多信息,请参阅XML序列化-何时使用DataContractSerializer/Binary/XMLSerializer或Data Contract Serializer-如何省略集合的外部元素。如果XSD与这些限制不兼容,则需要使用XmlSerializer

最新更新