我正试图从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
工作方式的协定,即应该序列化公共和私有字段,而不是属性。(有关更多信息,请参阅数据协定序列化程序支持的类型。)
要解决这个问题,您可以:
-
通过将
[XmlSerializerFormatAttribute]
应用于您的服务,将WCF配置为使用XmlSerializer
。要执行此操作,请参阅如何更改Wcf以使用不同的序列化程序?和使用XmlSerializer类,例如:[ServiceContract] [XmlSerializerFormat] public class MyApi { [OperationContract] public void CreateMeterConfig2(MeterConfig Payload) { //do nothing } }
-
通过使用
svcutil.exe
而不是xsd.exe
,从具有数据协定属性而不是XmlSerializer
属性的XSD中自动生成类。为此,请参阅从XSD和ServiceModel元数据实用工具(Svcutil.exe)生成DataContract注意,与
XmlSerializer
相比,DataContractSerializer
具有一些限制。例如,它不允许将属性选择性地序列化为XML属性而不是元素。有关更多信息,请参阅XML序列化-何时使用DataContractSerializer/Binary/XMLSerializer或Data Contract Serializer-如何省略集合的外部元素。如果XSD与这些限制不兼容,则需要使用XmlSerializer
。