SOAP WCF:防止反序列化到私有字段

时间:2016-03-29 14:04:57

标签: c# xml wcf soap

我正在尝试从SoapUI执行SOAP调用,针对WCF,并且在反序列化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>

1 个答案:

答案 0 :(得分:2)

您的问题是您自动生成了标有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. 使用XmlSerializer而不是svcutil.exe,使用数据合同属性而不是xsd.exe属性从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