【发布时间】:2017-11-06 21:27:50
【问题描述】:
我在 ASP.NET 网络服务上有一个 WebMethod,它返回一个枚举数组。如果添加了一个新值,并且该值由函数调用返回,那么 Web 服务的使用者将抛出异常,即使它并不关心该枚举值。
[WebMethod]
public UserRole[] GetRoles(string token)
部分 wsdl:
<s:simpleType name="UserRole">
<s:restriction base="s:string">
<s:enumeration value="Debug" />
<s:enumeration value="EventEditor" />
<s:enumeration value="InvoiceEntry" />
</s:restriction>
</s:simpleType>
(使用此 wsdl 编译消费者,但随后 wsdl 更改并且现在允许新值 - 如果返回该值,则客户端将引发 XML 异常。)
有没有办法覆盖这种类型的 SOAP 反序列化,以便我可以捕获错误并从数组中删除该项目或将其替换为默认值?如果这是使用 JSON 而不是 XML,我可以注册一个 JsonConverter 来处理该类型,所以我想我正在寻找一个类似的全局“RegisterConverter”类型函数。我认为不存在,但希望得到一些帮助......
任何用 Attributes 装饰 Enum 的方法都不起作用,因为所有代码都是由 wsdl 生成的,并在更新 Web 引用时重新生成。通常,如果我想修改由 wsdl 生成的类,我可以创建一个部分类,但这不适用于 Enum。甚至不确定我是否可以覆盖 XmlSerialization 代码,即使它是一个类。
一些额外的背景:
这实际上是作为我对动态枚举的尝试而实现的。 wsdl 是从数据库查找中生成的,因此我可以向数据库添加额外的值,并且消费应用程序将可以访问允许的值,而无需重新编译 web 服务。通过这种方式,我通过枚举类型获得智能感知和约束实施,但能够在不紧密耦合 Web 服务代码和客户端代码的情况下添加值。问题是,如果我添加一个新值,它可能会破坏未使用新 wsdl 更新的消费者……我宁愿忽略该值,因为消费者不知道如何处理无论如何。
SOAP 扩展可能是解决此问题的方法(我知道如何将 SOAP 扩展添加到 WebService 本身,但不知道如何在客户端添加一个...),但这并不理想,因为我真的很想有一种通用的方法来轻松处理这个问题,这样我就可以在我的代码中拥有更多动态枚举(它们并不是真正动态的,但想法是值通过 web 服务的中间层而无需重新编译那个中间层)。像“XmlSerialization.RegisterConverter(MyDynamicEnumType, DynamicEnum.Convert)”这样的东西是理想的,我可以定义一个通用函数来使用和注册。)
【问题讨论】:
-
好吧,我想到了两种可能的解决方案。一种是在 WebService 声明上覆盖 GetReaderForMessage(在部分类中),然后对枚举名称和值进行 Regex 匹配,另一种是将可接受值的列表发送到 Web 服务并让 Web 服务拒绝发送不在该列表中的值。这两个都很糟糕,我希望有人能提出比我迄今为止得到的更好的答案。如果没有,我明天会发布我自己的 janky 答案。
-
好吧,我确实最终覆盖了 GetReaderForMessage,但在枚举名称的整个消息字符串上进行的正则表达式匹配稍好...仍然希望有更好的方法来覆盖枚举的反序列化。跨度>
-
WSDL 和 XSD 的全部意义在于在服务和客户端之间建立一个契约,而您正在实施一些东西来打破这个契约。你不应该重新考虑一个不同的实现吗?或者更改 WSDL,以便允许任何内容而不是枚举。
-
如何违约? WSDL 会改变,但编译后的代码不能动态更新它的 wsdl,至少对于 .NET 的使用 Web 服务的实现来说是这样。我不能让对 wsdl 的每一次更改都成为重大更改,那将是混乱的。这只是一种将 web 服务代码与客户端代码解耦,并将代码与数据解耦,同时仍允许设计时智能感知和约束的方法。后者是枚举的用途。
-
如果你试图用一个整数替换 Enum 怎么办?并让客户决定如何处理它? (是否将其转换为枚举)
标签: c# soap enums webservices-client