【问题标题】:Make webservice client compatible to newer servers使 webservice 客户端与较新的服务器兼容
【发布时间】:2014-01-31 16:07:58
【问题描述】:

我们有一个 .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 }

错误

客户端知道 枚举 Colors 的值为 Red、Blue 和 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)

这个错误是正确的,因为它是一个枚举。但我正在寻找一种实用的方法来避免这种异常。您在堆栈跟踪中看到异常是由将响应 XML 数据反序列化为代理的 C# enum 的代码引发的。我们自己的代码已经可以忽略像Yellow 这样的未知枚举值。但是.NET 反序列化并不知道我们的需求。

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

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

【问题讨论】:

  • ASMX 是一项遗留技术,不应用于新开发。 WCF 或 ASP.NET Web API 应该用于 Web 服务客户端和服务器的所有新开发。一个提示:微软已经在 MSDN 上停用了ASMX Forum。
  • 务实的答案是,如果您将 WSDL 视为合同,您就不会有这些问题。
  • 你希望客户端对服务器发送它不理解的数据做什么?
  • 为什么不更新客户端呢?更新您的 Web 参考(或服务参考,如果您按照应有的方式使用 WCF),重建您的客户端并重新分发。
  • @JohnSaunders 我知道 ASMX 是一项传统技术。但是当 ASMX 更新时,我们已经开发了这个客户端。现在我们害怕将它转移到 WCF 因为努力。客户端有大约 100,000 行代码。

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


【解决方案1】:

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

但还有一个问题:webmethod 需要获取SoapExtensionAttribute(子类)。但是具有该 webmethod 的代理类是生成的代码(来自 *.wsdl)。 所以我们需要在每次生成代码时设置这个属性。配置的另一个选项是imo不可能的,因为我们有一个MMC Snap-In,一个*.dll。

【讨论】:

    猜你喜欢
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 2021-12-24
    相关资源
    最近更新 更多