使webservice客户端与更新的服务器兼容

时间:2014-01-31 16:07:59

标签: c# enums .net-3.5 wsdl asmx

我们有一个.NET客户端,它使用wsdl.exe从wsdl文件生成的代理类(派生自System.Web.Services.Protocols.SoapHttpClientProtocol)。

到目前为止,我们在客户端和Web服务之间具有良好的兼容性,可以进行大多数Web服务更改。 旧客户端(具有从旧wsdl文件生成的旧代理)将不会调用新的Web服务方法。
唯一的问题是枚举类型的扩展(xsd.enumeration)。此特殊枚举用于许多get...次调用。

示例

WSDL

  <xsd:simpleType name="Colors">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="Red"/>
      <xsd:enumeration value="Blue"/>
      <xsd:enumeration value="Unspecified"/>
    </xsd:restriction>
  </xsd:simpleType>

从WSDL生成的代理代码

[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:archive.admin.services.ecm.opentext.com")]
public enum Colors { Red, Blue, Unspecified }

错误

客户端知道值为ColorsRedBlue枚举 Unspecified。如果服务器返回一个新的枚举值,如Yellow,我们会收到错误:

Instance validation error: 'Yellow' is not a valid value for Colors.
Exception Class: System.InvalidOperationException
StackTrace:
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderArchiveAdministrationService.Read2_Keys(String s)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderArchiveAdministrationService.Read6_ResultField(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderArchiveAdministrationService.Read7_ResultRecord(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderArchiveAdministrationService.Read10_invokeCommandResponse()
   at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer.Deserialize(XmlSerializationReader reader)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
There is an error in XML document (1, 1557).
Exception Class: System.InvalidOperationException
StackTrace:
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)

此错误是正确的,因为它是 枚举 。但我寻找一种务实的方法来避免这种异常。您在stacktrace中看到,将响应XML数据反序列化为代理的C#枚举的代码抛出异常。我们自己的代码已经可以忽略未知的枚举值,如Yellow。但.NET反序列化并不了解我们的需求。

我已找到SoapExtensions。但是,我需要解析每个Web服务响应的整个XML内容。

您是否有想法/解决方案/解决方法以避免上述异常? 请不要警告我“这是坏事”,“wsdl是合同”等等。我只想要一个务实的解决方案。 : - )

1 个答案:

答案 0 :(得分:0)

我用SoapExtension做到了。 我使用了TraceExtension示例并对其进行了修改,以便检查每个响应XML是否包含未知的enum文字。如果找到一个,则扩展名会以未使用的enum文字(Unspecified)替换为XML格式。
客户端代码然后忽略文字Unspecified

但是还有一个问题:webmethod需要获得SoapExtensionAttribute(子类)。但是使用该webmethod的代理类是生成的代码(来自* .wsdl)。 因此我们需要在每次生成代码时设置此属性。配置的另一个选项是不可能的,因为我们有一个MMC管理单元,一个* .dll。