通常,定义消息的架构时使用数据协定就足够了
有时必须精确控制如何将类型映射到通过网络传输的SOAP消息。
对于这种情况,最常见的方案是插入自定义SOP标头。
另一种常见方案是定义消息头和正文的安全属性,也就是说,确定是否对这些元素进行数字签名和加密。消息样式的操作可提供这种控制。
消息样式的操作最多具有一个参数和一个返回值,其中参数和返回值的类型都是消息类型;也就是说,这两种类型可直接序列化为指定的SOP消息结构。
可以是用MessageCOntractAttribute标记的任何类型或Message类型。
若要为某一类型定义消息协定(即定义该类型和SOAP信封之间的映射),请对该类型应用MessageContractAttribute.然后对该类型中要成为SOAP标头的成员应用MessageHeaderAttribute,并对要成为消息的SOAP正文部分的成员应用MessageBodyMemberAttibute.
可以对所有字段、属性和事件应用MessageHeaderAttribute和MessageBodyMemberAttribute,而不管这些字段、属性和事件是公用的、私有的、受保护的还是内部的
每个单独的消息头和消息正文部分均使用为消息所使用的服务协定选择的序列化引擎进行序列化(转换为XML).
默认序列化引擎XmlFormatter可以显式处理(通过具有System.Runtime.Serialization.DataContractAttribute)或隐式处理(通过作为基元类型而具有System.SerializableAttribute等)具有数据协定的任何类型
可以采用两种方式在消息协定中使用重复元素的数组。直接在数组上使用MessageHeaderAttribute或MessageBodyMemberAttribute,另外就是直接使用MessageHeaderArrayAttribute
消息协定可以指示消息和正文是否应进行数字签名和加密
通过在MessageHeaderAttribute和MessageBodyMemberAttribute属性(attribute)上设置System.ServiceModel.MessageContractMemberAttributre.ProtectionLevel属性(property)来完成
System.Net.Security.ProtectionLevel
None(不加密或 签名)
Sign(近数字签名)
EncryptAndSign(加密并数字签名)
默认值为None
若要让这些安全功能起作用,必需正确配置绑定和行为。如果在没有正确配置的情况下使用这些安全功能(例如,在不提供凭据的情况下试图对消息进行签名),则会在验证时引发异常
对于消息头,会分别为每个消息头确定其保护级别
对于消息正文,保护级别可理解为“最低保护级别”。无论包含几个正文部分,正文都只有一个保护级别。正文的保护级别由所有正文部分的最高ProtectionLevel属性设置确定。不过,您应该将每个正文部分的保护级别设置为实际要求的最低保护级别
在消息协定的SOAP表示形式中,每个标头和正文部分都映射为一个具有名称和命名空间的XML元素。通过操作System.ServiceModel.MessageContractMemberAttribute.Name和System.ServiceModel.MessageContractMemberAttribute.NameSpace(在MessageHeaderAttribute和MessageBodyMemberAttribute属性的父类上)可以更改这些默认值
默认情况下,SOAP正文部分会在包装元素内部进行序列化
若要取消包装元素,请将IsWrapped舒心设置为false.
若要控制包装元素的名称和命名空间,请使用WrapperName和WrapperNameSpace属性
SOAP标准定义了下列可存在于标头上的属性:
Actor/Role(在SOAP1.1中为Actor,在SOAP1.2中为Role)指定要使用给定标头的节点的统一资源标识符
MustUnderstand指定醋栗标头的节点是否必须理解该标头
Relay指定要将标头中继大下游节点
WCF不会对传入消息的这些属性执行任何处理(MustUnderstand除外)
静态方式将这些属性设置为任何需要的值
也可以通过代码以动态方式控制这些属性
如果同时使用动态和静态控制机制,则静态设置用作默认设置,但可以在以后使用动态机制重写
默认情况下,正文元素采用字母顺序
可以通过System.ServiceModel.MessageBodyMemberAttribute.Order属性进行控制
在消息协定中,基类型正文成员不排列在派生类型正文成员之前
更改消息协定
应用程序的新版本可能会向消息中添加额外的标头。在从新版本应用程序向旧版本应用程序发送消息时,系统必需处理额外的标头,同样,反方向操作时系统必需处理缺少的标头
下面的规则适用于标头的版本管理:
WCF不反对缺少标头,相应的成员将保留其默认值。
WCF还忽略意外的额外标头,此规则的一种例外情况在传入的SOAP消息中,额外标头的MustUnderstand属性设置为true.在这种情况下,由于存在一个无法处理但必需理解的标头,因此会引发异常。
消息正文具有类似的版本管理规则,即忽略缺少和附加的消息正文部分
性能注意事项
每个消息头和消息正文部分相互独立的进行序列化。因此,可以为每个标头和正文部分重新声明相同的命名空间。为了提高性能,特别是对于消息在网络上的大小,请将多个标头和正文部分合并成一个标头或正文部分