- WSDL:=契约+策略.
- 契约主要关注操作的消息类型.
- 策略为操作描述协议.
- 当契约变化时,使用老契约的客户应能够继续使用,并且使用新的契约内容.一旦发布.契约就确定了.
- 但是,策略是可以改变的.如果客户端可以动态的处理变化,那么改变策略就是安全的.
- 服务契约
- 允许多余,缺失的参数数量.分别会被忽略,赋予默认值.
- 对应参数和返回值的类型,若不兼容会Error.
- 调用被删除的操作会异常.
- 新追加的操作不能够被调用到.
- 数据契约
- 非必须成员,没有问题.
- 对于必须成员(IsRequried=true),由于WCF要求其在被序列化之前必须被赋值,所以会出现异常(NetDispatcherFaultException).
-
客户端与服务器段可以独立的设置自己的必须数据成员,越多交互越安全,但是会降低灵活性与版本兼容性.
- 修改成员的类型.修改后类型兼容时,没有问题.不兼容时结果不定.
-
WCF对于枚举、委托、DataSet和DataTable、泛型、集合的支持有限.
-
枚举:自身支持序列化,所以默认就是在数据契约里,当只需要其一部分被序列化时,使用EnumMember表示出需要的数据.在客户端只有被EnumMember的数据才出现在枚举定义里.
-
委托:WCF对委托以及事件的支持都不够好。这是因为委托的内部调用列表的具体结构是本地的,客户端或服务无法跨服务边界共享委托列表的结构。此外,我们不能保证内部列表中的目标对象都是可序列化的,或者都是有效的数据契约。这会导致序列化的操作时而成功,时而失败。因此,最佳实践是不要将委托成员或事件作为数据契约的一部分.
-
数据集和数据表: 是可以序列化的.在服务契约中使用该类型,代理类中只会有一个定义,而没有任何代码.我们可以手工修改. 然而,WCF的最佳实践则是避免使用DataTable和DataSet,以及使用DataTable和DataSet的类型安全的子类。这种方式过于繁琐。而且,这些数据访问类型都是特定的.NET类型。在序列化时,它们生成的数据契约样式过于复杂,很难与其它平台进行交互。在服务契约中使用数据表或者数据集还存在一个缺陷,那就是它可能暴露内部的数据结构。同时,将来对数据库样式的修改会影响到客户端。虽然在应用程序内部可以传递数据表,但如果是跨越应用程序或公有的服务边界发送数据表,却并非一个好的主意。通常情况下,更好的做法是暴露数据的操作而非数据本身。最好的做法是将DataTable转换为数组类型.
-
泛型: 不能在数据契约里定义泛型,但是,可以在服务段使用泛型,但是在生成的数据契约定义中,泛型被具体的类型(<原有名>Of<类型参数名><哈希值>)代替.WCF还支持将自定义类型作为泛型参数。此外,还可以通过数据契约的Name属性为导出的数据契约指定不同的名字.
-
集合:WCF支持泛型集合、定制集合.但是有很多限制.对于自定义的集合应该采用
- [KnownType(typeof(Document))]
- [CollectionDataContract]
- [Serializable]
- public class DocumentList:IList<Document>
- 这样,客户端应用程序可以直接使用数据契约,仍然能够识别.
- IextensibleDataObject
- 实现对多余数据的临时存储.
- 客户端代理缺省对其进行了实现.这样,老版本能够保存新版本传递的数据,以便在更新时能够包含原始的数据.
- 可以在Server端实现.来保存客户端传入的未知数据.
- 场景:调用新版本服务,但是需要老版本进行实际的处理时.
- 但是会带来DOS攻击和非必要的使用服务器资源的问题.
- 可以使用配置和代码来关闭.
- 其好处是不会导致数据丢失,但是增加了传输的数据量.
- 版本控制
- 只有签名变化时,才会形成新版本.
-
1)非严格:当方法的签名变化(除添加,删除参数外,但是当该参数为重要信息时有风险)时,即删除操作或参数类型变化时才使用新版。实现:在现有的契约上添加新方法,使用相同的NameSpace,更新客户端.
-
2)半严格:在添加操作后,要生成一个继承自旧版的一个新契约.原有的版本不再向外提供服务端点,但对原版本客户端无影响;新对新,老对老。
- 3)新老服务之间没有任何关系。