WCF 向后兼容性和版本控制策略 – 第一部分






4.17/5 (5投票s)
WCF 数据契约和服务契约版本控制的几个方面以及为契约提供向后兼容性所采用的实践。
引言
本文说明了 WCF 数据契约和服务契约版本控制的几个方面以及为契约提供向后兼容性所采用的实践。一旦服务开发完成并投入生产,契约中的任何更改都应该是向后兼容的,以便在部署更改时现有客户端不受影响。我们将探讨数据契约和服务契约更改的影响,并尝试根据场景采用版本控制策略。在本文的第一部分,我们将探讨 WCF 框架在服务契约操作版本控制的不同情况下的行为。
跨契约的向后兼容性
WCF 服务的修改可能发生在数据契约或服务契约的操作中。在这两种情况下,默认情况下,WCF 都具有版本容错能力。框架会尽最大努力为现有客户端提供向后兼容性。让我们通过一个例子来探讨不同的情况。为了探索 WCF 的向后兼容性行为,我们将开发一个简单的 WCF 服务项目。WCF 服务有一个名为 GetData()
的单个方法。
实现 WCF 服务
为了探索 WCF 的向后兼容性行为,我们将开发一个简单的 WCF 服务项目。WCF 服务有一个名为 GetData()
的单个方法,该方法有一个“integer”类型的参数并返回“string”。
服务实现如下
完成 WCF 服务开发后,右键单击 MyService.svc 文件 -> 在浏览器中查看,以检查 WCF 服务生成的 WSDL。
开发一个控制台应用程序以测试服务。
右键单击 **References->Add Service Reference**。单击 **Discover** 或在 **Address** 框中键入服务 URL。单击 **OK** 后,将生成存根代码。现在使用以下代码在控制台应用程序中调用服务
运行控制台应用程序。应生成以下输出
修改服务契约
现在让我们检查客户端在修改服务契约情况下的行为
情况 1:向操作签名添加新参数
修改服务方法 GetData()
。向方法添加一个新的“integer”参数。另外,让我们更改服务实现。
这是修改后的服务契约
修改后的服务实现:我们将新传递的参数与现有参数一起添加。
构建服务。
现在运行现有的使用者客户端控制台应用程序,而不更新服务引用。我们想使用旧的存根代码和方法签名来调用服务。您应该会看到以下输出
我们可以看到,在向服务方法添加新参数时,服务现有客户端不受影响。实际上,新参数在服务中被初始化为默认值。在我们的例子中,由于我们引入了一个新的“integer”类型参数,其默认值为“0”。因此,当旧方法签名调用服务时,值“0”被用作新“integer”类型参数的值。
情况 2:从操作签名中删除参数
修改服务方法 GetData()
。删除两个参数。另外,让我们更改服务实现。
修改后的服务契约
修改后的服务实现:我们已从服务中删除了两个参数。
构建服务。
现在运行现有的使用者客户端控制台应用程序,而不更新服务引用。我们想使用旧的存根代码和方法签名来调用服务。您应该会看到以下输出
我们可以看到,在从服务方法中删除参数时,服务现有客户端不受影响。实际上,客户端传递的多余参数在服务端被忽略,这会导致服务端数据丢失。
情况 3:修改操作的参数类型
修改服务方法 GetData()
。为了修改与现有客户端存根方法签名对应的参数类型,让我们向方法添加一个新的“string”参数。另外,让我们更改服务实现。
修改后的服务契约
修改后的服务实现:我们已从服务中删除了两个参数。
构建服务。
现在运行现有的使用者客户端控制台应用程序,而不更新服务引用。我们想使用旧的存根代码和方法签名来调用服务。您应该会看到以下输出
现有的客户端应用程序运行,但无法显示调用者传递的任何值。实际上,在这种情况下,结果是出乎意料的。如果来自客户端的传入类型无法转换为参数数据类型,则应该会引发异常。
情况 4:修改返回值类型
修改服务方法 GetData()
以返回“integer”类型。另外,更改服务实现。
修改后的服务契约
修改后的服务实现:我们已从服务中删除了两个参数。
构建服务。
现在运行现有的使用者客户端控制台应用程序,而不更新服务引用。我们想使用旧的存根代码和方法签名来调用服务。您应该会看到以下输出
现有的客户端应用程序运行并显示调用者传递的值。同样,在这种情况下,结果是出乎意料的。如果服务返回值无法转换为操作签名客户端版本中的预期数据类型,则应该会引发异常。我们现有的客户端代码以值 4 调用服务方法。在服务端,返回整数值 4。现在,客户端端的预期返回类型是“string”。因此,“integer”4 已转换为“string”4。
情况 5:添加新操作
添加新的服务方法 GetNewData()
并在服务端实现。
新的服务方法
服务实现
构建服务。
现在运行现有的使用者客户端控制台应用程序,而不更新服务引用。我们想使用旧的存根代码和方法签名来调用服务。您应该会看到以下输出
因此,现有客户端不受影响,也不会调用完全未知的操作。
情况 6:删除现有操作
删除现有的服务方法 GetData()
。现在服务只有一个方法 GetNewData()
。
注释掉现有的服务方法
注释掉现有的实现
构建服务。
现在运行现有的使用者客户端控制台应用程序,而不更新服务引用。对于客户端的旧存根代码,正在调用 GetData()
方法。应该会发生以下错误:
在这种情况下,客户端发送到服务端的消息被视为使用了未知操作头。结果,引发了异常。
我试图讨论服务契约操作版本控制的一些可能情况。在本文的下一部分,我将探讨 WCF 框架在数据契约版本控制的不同情况下的行为。