我正在尝试从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>
答案 0 :(得分:2)
您的问题是您自动生成了标有XmlSerializer
-specific attributes的类型,但正在使用uses DataContractSerializer
by default的WCF。当DataContractSerializer
尝试序列化标有[SerializableAttribute]
但没有data contract attributes的类型时,它会推断出与BinaryFormatter
工作方式类似的合同,即公共和私有字段应序列化,不是属性。 (有关更多信息,请参阅Types Supported by the Data Contract Serializer。)
要解决此问题,您可以:
通过将[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
}
}
使用XmlSerializer
而不是svcutil.exe
,使用数据合同属性而不是xsd.exe
属性从XSD自动生成类。为此,请参阅Generate DataContract from XSD和ServiceModel Metadata Utility Tool (Svcutil.exe)。
请注意DataContractSerializer
与XmlSerializer
相比有一些限制。例如,它不允许将属性选择性地序列化为XML属性而不是元素。有关更多信息,请参阅XML Serialisation - When To Use DataContractSerializer / Binary / XMLSerialiser或Data Contract Serializer - How to omit the outer element of a collection。如果您的XSD与这些限制不兼容,则需要使用XmlSerializer
。