WCF合约更改对客户端的影响

9
我想知道哪些WCF合同(接口)类型更改会导致客户端尝试发送消息失败,以及为什么。我相信WCF可以处理某些差异,但我不确定哪些改变是安全的,哪些是不安全的。
  • 增加/删除操作契约(OperationContract)的参数?
  • 增加/删除/修改DataContract序列化属性?
  • 增加/删除服务契约(ServiceContract)的操作契约(OperationContract)?
一个朋友在这里提出了类似的问题:

将方法添加到WCF ServiceContract是否会破坏现有的客户端?

编辑:正如John Saunders指出的那样,通常更改合同并不是一个好主意,但内置的一些东西允许一定程度的版本容差(ExtensionDataObject等)。我只想知道版本容差有多灵活。
5个回答

17

请查看这篇关于dasBlonde的文章:版本控制WCF服务契约

它列出了哪些更改将打破现有客户端:

  1. 移除操作
  2. 更改操作名称
  3. 删除操作参数
  4. 添加操作参数
  5. 更改操作参数名称或数据类型
  6. 更改操作的返回值类型
  7. 通过显式使用.NET属性或自定义序列化代码,更改参数类型(数据合同)或操作(消息合同)的序列化XML格式
  8. 修改服务操作编码格式(RPC编码 vs.文档文字)

Michele的这篇文章更详细地解释了如何设计更灵活的契约。


如果你需要做这些事情之一,请更新你的客户端。使用VS2015很容易。 - ZX9
将一个非空的Guid合同属性变为可为空,会影响客户端吗? - Jurijs Kastanovs
命名空间怎么样?更改命名空间会破坏合同吗?毕竟它在序列化后仍然是相同的。 - Li3ro

4

合同设计建议

  1. 第一个版本

    1.1. 为所有合同(接口、方法、类和属性)精心选择名称。这些名称将在未来的版本中难以更改。

    1.2. 请记住,以下内容在未来无法更改:方法参数的数量;对于不受您控制的类型,参数/返回值/属性的类型。

  2. 下一个版本

    2.1. 如果已存在,请勿更改任何xxxContractAttribute的Namespace或Name参数。

    2.2. 如果已存在,请勿更改DataMemberAttribute的Order属性。

    2.3. 只允许以下更改:

    • 在接口(ServiceContract)上添加方法(OperationContract)

    • 在接口上重命名方法

    • 重命名类(DataContract)

    • 在类(DataContract)上添加属性(DataMember)

    • 在类上重命名属性

    2.4. 任何删除都会破坏兼容性。

    2.5. 任何其他更改都会破坏兼容性。

以下是一些有用的链接:


3
在WCF中,“添加/删除OperationContract中的参数”不一定会破坏您的客户端,但您必须知道自己在做什么。
特别是,向操作契约添加新参数将导致旧客户端无法传递它们,并且在服务端上,它们将使用其默认值进行设置。
此外,从操作契约中删除参数,在客户端方面将保持沉默,并且在服务端上它们将被简单地忽略。
当然,更改参数的名称/类型将导致客户端出现问题。

1

好的。问题是由于错误的命名语法(参数使用大写字母指定),我想要调整一些代码:

[OperationContract]
public void Foo(string Bar){}

[OperationContract]
public void Foo(string bar){}

调整资本是否会违反合同?

3
是的,但如果你只是想为你的代码目的使用小写的 bar,我认为你可以用 [MessageParameter(Name ="Bar")] 来修饰参数本身,这样它在客户端看起来就一样了,但在服务内部却不同。 - Jeremy

0

我认为最佳实践是将合同视为不可打破的,嗯,合同。一旦发布,不要更改它们。很容易使用所需更改创建新合同,并在新端点上公开新合同。


1
我同意不更改合同的整体概念,但如果对合同进行小的更改,我不知道为每个新合同发布一个新的端点是否总是一个好主意。你对此有什么想法吗? - Andy White
1
我的想法是,“给他们一英寸,他们就会取得一英里”。不要养成容许“小”更改的习惯,否则他们会做出大的更改。 - John Saunders

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接