受支持的消息交换方案

工作流服务支持在 Windows Communication Foundation (WCF) 中定义的一些消息交换方案。 单向发送和请求/响应是两种受支持的方案。 在单向发送方案中,客户端在对工作流服务调用操作时不需要得到响应。 它只需调用该操作并继续执行其余任务。 在请求/响应方案中,客户端需要得到工作流服务的响应,并且它会阻止主要执行线程,直到得到响应。 如这些方案中所指出,客户端会启动与工作流服务的所有消息交换。

双工通信可通过两种方法来实现。 第一种方法是:使用双工协定(如普通的 WCF 服务)创建将用于异步通信的会话 ID。 不幸的是,因为会话 ID 直接附加到双工通道,所以,只要通道损坏,就无法再使用会话 ID 在客户端和服务之间创建上下文。 第二种启用双工通信的方法是:使用利用独立通道进行通信的相关协定。 这些协定通过它们的初始操作调用传递上下文 ID 信息,并且操作状态可以像任何其他工作流服务一样保留下来。 通过使用相关的单向协定,上下文 ID 存储在应用程序层,因此,如果客户端或服务两者之中的任意一者重新启动,则它们都可以从它们最后的保留状态中恢复。 这是工作流服务进行双工作通信的首选方法。

作为最佳做法,您应该在进行异步通信之前对服务执行一个同步请求/响应操作。 通过这种交换,客户端和服务将可以创建可在将来的操作调用中使用的上下文。

上下文交换

本节介绍工作流和持久性服务如何使用上下文在服务和客户端之间建立消息关联。 在执行初始请求/响应操作后,客户端会从服务接收上下文,并在消息交换生存期内向服务提供针对所有将来消息的同一上下文。 上下文对客户端而言是不透明的,并且提供上下文只是为了通过已创建的消息交换来与给定服务实例保持通信。 创建上下文后,只能由来自服务的传入消息对它进行修改。

备注

如果是双工方案,则服务会将上下文以上下文头的形式重新发送给客户端(作为从服务发送到客户端的第一条消息的一部分,但不一定作为客户端发出的第一个请求的响应)。

在服务端,通道实例负责将客户端提供的上下文(采用传入消息中的 SOAP 标头的形式)转换为 ContextMessageProperty 类型。 之后,堆栈中靠上的应用程序层或通道就可以使用 ContextMessageProperty 了。 服务端通道还允许应用程序层指定要传播回到客户端的新上下文值。

通过在应用程序层维护该上下文,可以移除原始通道并创建一个新通道。 虽然上下文交换机制由通道提供,但应用程序层也可以提供和恢复实际上下文(在客户端和服务上均可以)。

对于使用 HTTP 传输的服务终结点和都允许使用 HTTP Cookie 的客户端,可以使用 HttpCookie 机制来交换应用程序上下文。 上下文交换协议允许客户端通道接受某个服务提供的上下文,并将其应用于所有后续请求,以便该服务可以接收通过相同客户端通道实例发送的请求。 上下文交换协议还提供一种基于 SOAP 的功能,它等效于 HTTP Cookie 在传输层提供的功能。

备注

如果客户端是基于工作流的并且使用 SendActivity 活动与持久性服务或工作流服务进行通信,则此类客户端必须使用包含 ContextBindingElement 的绑定来在客户端和服务之间交换上下文,或提供与 ContextMessageProperty 集成的其他某个相关通道。

SOAP 标头是用于表示上下文信息的 wsc:Context SOAP 标头。 上下文标头架构允许使用任意数量的子元素,且每个子元素都具有字符串内容。 这样,表示上下文的相应消息属性便可以使用便捷的词典,该词典将 XML 限定名(wsc:Context 标头中的子元素名称和命名空间)映射到字符串值(wsc:Context 标头中的子元素的文本值)。 因此,当绑定提供消息保护功能时,需要在 SOAP 或传输级别对 wcs:Context 标头进行数字签名。

获取和设置上下文

上一节中介绍的 ContextMessageProperty 是一种消息属性,用于在客户端或服务端的应用程序层和通道层之间交换上下文。 如果上下文是在通道层创建的,则客户端和服务上的所有传入消息都将具有由上下文通道附加的这一属性。 如果上下文在客户端或服务上的应用程序层附加到传出消息,则存储在通道层的上下文将由 ContextMessageProperty 表示的上下文替换。

除了可以在客户端或服务端使用的 ContextMessageProperty 之外,在客户端,还可以获取当前上下文或者使用 IContextManager 对通道实例设置新上下文,如下面的示例所示:

IDictionary<XmlQualifiedName, string> context;
IContextManager cm = ClientProxy.InnerChannel.GetProperty<IContextManager>();
if (cm != null)
    context = cm.GetContext();
IContextManager cm = ClientProxy.InnerChannel.GetProperty<IContextManager>();
if (cm != null)
    context = cm.SetContext();

备注

ClientProxy 对象是一个 svcutil 生成的代理类的实例,用于对服务进行操作调用。

请参见

概念

工作流服务创作样式

其他资源

创建工作流服务和持久性服务

Footer image

版权所有 (C) 2007 Microsoft Corporation。保留所有权利。