WCF服务中自定义类型的Xml序列化

时间:2012-05-15 10:22:34

标签: wcf c#-4.0 xml-serialization

我是WCF的新手。我为它开发了一个WCF服务和客户端。服务方法将检索使用自定义XML序列化程序的自定义数据。我读过,在这种情况下,合同方法应标有[XmlSerializerFormat]

[ServiceContract]
[XmlSerializerFormat]
public interface ITSService
{
    [OperationContract]
    [XmlSerializerFormat]
    ProtocolDocument GetReferenceData(string referenceType, SerializableDictionary<string, string> args);

ProtocolDocument实施IXmlSerializable

[XmlRoot("protocol", Namespace = Protocol30Namespace)]
[Type(Name = "protocol", Namespace = Protocol30Namespace)]
public class ProtocolDocument : ProtocolElement, ICloneable, IXmlSerializable

VS 2010默认选择wsHttpBinding。我不需要安全,所以我把它关掉了。

以下是服务配置:

<services>
   <service name="MyNamespace.TSService" 
            behaviorConfiguration="MyNamespace.TSServiceBehavior">
      <host>
         <baseAddresses>
            <add baseAddress = "http://localhost:51944/TSService.svc" />
         </baseAddresses>
      </host>
      <endpoint 
          address="" 
          binding="wsHttpBinding" 
          bindingConfiguration="nonSecurityWSHttpBinding"
          contract="MyNamespace.ITSService">
         <identity>
            <dns value="localhost"/>
         </identity>
      </endpoint>
      <endpoint 
          address="mex" 
          binding="mexHttpBinding" 
          contract="IMetadataExchange"/>
   </service>
</services>
<behaviors>
   <serviceBehaviors>
      <behavior name="MyNamespace.TSServiceBehavior">
         <serviceMetadata httpGetEnabled="true" />
         <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
   </serviceBehaviors>
</behaviors>
<bindings>
   <wsHttpBinding>
      <binding name="nonSecurityWSHttpBinding">
         <security mode="None">
            <transport clientCredentialType="None"/>
         </security>
      </binding>
   </wsHttpBinding>
</bindings>

然后我为此服务生成了客户端,但结果无法反序列化。 Fiddler说,SOAP将序列化数据包装到GetReferenceDataResultGetReferenceDataResponse

 <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://tempuri.org/ITourSystemService/GetReferenceDataResponse</a:Action>
    <a:RelatesTo>urn:uuid:3d7f6dc0-4961-4bc5-b1fc-c9997af9fbd4</a:RelatesTo>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <GetReferenceDataResponse xmlns="http://tempuri.org/">
      <GetReferenceDataResult>
          <header version="3.0" language="Russian"/>
          <references/>
      </GetReferenceDataResult>
    </GetReferenceDataResponse>
  </s:Body>
</s:Envelope>

但缺少根元素!我该怎么办?

PS序列化impl:

 void IXmlSerializable.ReadXml(XmlReader reader)
{
    var serializer = new ProtocolDocumentXmlSerializer();
    serializer.Deserialize(this, reader);
}

void IXmlSerializable.WriteXml(XmlWriter writer)
{
    //
    // Serialize everything except the root element, because it was already written by .NET XML-serialization mechanism
    var xmlSerializationFlags = XmlSerializationFlags.All & ~XmlSerializationFlags.IncludeRootElement;

    var serializer = new ProtocolDocumentXmlSerializer();
    serializer.Serialize(this, writer, xmlSerializationFlags);
}

Xml序列化效果很好。它已经在使用中。我想我的WCF配置错了。

1 个答案:

答案 0 :(得分:0)

您似乎明确告诉它忽略WriteXml方法中的根元素 - 这就是为什么没有根元素

var xmlSerializationFlags = XmlSerializationFlags.All & ~XmlSerializationFlags.IncludeRootElement;

如果无法使反序列化工作,您可以始终使用Message作为客户端契约中的返回类型在XML级别工作,然后对消息调用GetReaderAtBody,将数据加载到XElement并使用LINQ to XML转换将XML转换为在客户端使用的对象