对话示例

本示例演示工作流服务如何通过同一个协定与多个客户端进行并行对话。示例演示如何关联针对同一个协定和同一个操作而发送的、但由于由不同客户端发送而必须进行不同处理的消息。为了实现并行对话,本示例使用工作流服务提供的对话上下文功能。

提示

此示例需要安装 .NET Framework 3.5 版才能生成和运行。若要打开项目和解决方案文件,需要使用 Visual Studio 2008。

有关 设置此示例的更多信息,请参见 One-time Setup Procedure for Windows Communication Foundation Samples

本示例还使用异步双工通信使工作流服务和客户端可以异步通信。在双工通信中,开始通信之前,两个应用程序必须交换上下文。启动对话的服务在其消息的答复中接收上下文。工作流服务提供此功能。为支持从接收服务到启动服务的通信,启动服务必须在第一个消息中发送其上下文信息。下图显示了示例的体系结构。

对话示例体系结构

对话示例

本示例实现下面的方案。

客户发送一个订单请求。在响应此请求时,供应商需要从三个不同的逻辑提供程序获取报价以发送订单。供应商向所有三个供应商各发送一个消息。每个提供程序通过对同一个协定调用相同的操作,发回一个报价。由于供应商工作流使用对话上下文,因而上下文功能可将报价与正确的接收活动关联起来以便进一步处理报价。供应商接收所有报价,挑选最低报价并将它发送给客户。

本示例中有五个实体进行通信:

  • 客户服务
    客户服务向供应商发送订单详细信息以及供应商服务稍后用于与客户服务进行通信的上下文。此基本工作流包含初始 Send 活动,该活动随采购订单和上下文一起作为负载发送采购订单请求消息。Receive 活动等待来自供应商服务的响应。
    客户服务发送的上下文与 Receive 活动相关联。Send 活动的“发送前”处理程序包含用于从 Receive 活动获取上下文的代码。Receive 活动包括下面的 GetContext 方法,调用该方法可获取上下文。

    private void PrepareOrder(object sender, SendActivityEventArgs e)
    {
        this.order.Amount = 1000;
        this.order.OrderId = 1234;
        this.contextToSend = this.ReceiveOrderDetails.Context;
    }
    
  • 供应商服务
    供应商服务与三个逻辑提供程序通信。为此,该服务使用每个对话的唯一上下文令牌和异步双工通信的组合。它在客户和供应商服务之间的通信正文中发送上下文。
    与逻辑提供程序通信之前,供应商服务先从客户服务接收消息。在此消息中,供应商服务还接收用于与客户服务进行通信的上下文。供应商服务工作流将此上下文应用于 Send 活动,该活动用于将消息发送给客户端服务。实现此功能的代码位于第一个 Receive 活动内 Code 活动的代码处理程序中,如下面的代码所示。

    private void AcceptOrder(object sender, EventArgs e)
    {
        Console.WriteLine("Order Received...");
        this.supplierAck = "Order Received on " + DateTime.Now;
        this.SendOrderDetails.Context = this.customerContext;
    }
    

    供应商服务从客户接收到消息后,供应商使用三个逻辑提供程序启动三个并行对话。每个对话分支均有一个 Send 和一个 Receive 活动,如前面的图示所示。每个分支中的 Send 活动都会将消息发送到一个逻辑提供程序。该分支中的相应 Receive 活动必须从供应商检索该消息。为此,消息负载中的 Send 活动必须在负载中发送唯一的上下文。逻辑提供程序随后在与报价一起发回消息时,将在消息头中使用此上下文。
    默认情况下,每个 Receive 活动均有一个根上下文。为了使 Receive 活动具有唯一性,Receive 活动应定义一个限定于父活动(根活动除外)的上下文。在下面的示例中,并行对话中的每个 Receive 活动的上下文令牌属性都具有唯一的名称并限定于包含该活动的并行活动。每个并行分支内的 Send 活动从 Receive 活动中获取上下文时,所获取的上下文对于该 Receive 活动是唯一的。此唯一的上下文还可用于创建 Receive 活动所侦听的队列的队列名称。当逻辑提供程序在标头中与上下文一起发回报价时,工作流服务调度层将使用该报价创建相应的队列名称和队列消息,Receive 活动随后将查看该消息。
    private void PrepareShipper2Request(object sender, SendActivityEventArgs e)
    {
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine("RequestShippingQuote from Shipper2");
    Console.ResetColor();
    this.contextShipper2 = this.ReceiveQuoteFromShipper2.Context;
    }
    逻辑提供程序工作流从供应商接收报价请求以及上下文。该上下文应用于将消息发回供应商的 Send 活动,如下面的代码所示。

    private void AcceptQuoteRequest(object sender, EventArgs e)
    {
        Console.ForegroundColor = ConsoleColor.White;
        Console.WriteLine("Received ShippingQuote Request");
        this.supplierAck = "Working on quote...";
        Console.ResetColor();
        this.SendShippingQuote.Context(this.supplierContext);
    }
    

设置、生成和运行示例

  1. 默认情况下,本示例不使用持久性。如果需要持久性,则必须在每个解决方案的 App.config 文件中添加 <WorkflowRuntime> 项。该项应该位于 behaviors 节的下面,如下面的示例所示。

    <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehavior"  >
              <serviceMetadata httpGetEnabled="false" />
              <serviceDebug includeExceptionDetailInFaults="true" />
              <workflowRuntime name="WorkflowServiceHostRuntime" validateOnCreate="true" enablePerformanceCounters="true">
                <services>
                  <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                       connectionString="Data Source=localhost\sqlexpress;Initial Catalog=ServiceModelSamples_ServiceWorkflowStore;Integrated Security=True;Pooling=False"
                       LoadIntervalSeconds="1" UnLoadOnIdle= "true" />
                </services>
              </workflowRuntime>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
  2. behaviors 节下面的 <WorkflowRuntime> 项外,还需添加 SQL 持久性服务。运行位于 One-Time Setup Procedure for the Windows Communication Foundation Samples主题中的 CreateStores.cmd 脚本。CreateStores.cmd 脚本可创建 ServiceModelSamples_ServiceWorkflowStore 数据库。默认情况下,将在 SQL Server 2005 Express Edition 数据库中创建这些数据库。请确保在您的计算机上已经安装了 SQL Server Express。如果您不想安装 SQL Server Express,而是想使用 SQL Server,请确保修改持久性数据库的 App.config 文件中的连接字符串。

  3. 所有工作流服务都运行后,在客户端工作流中按 Enter 可查看相互通信的所有工作流。采购订单将发送给供应商,而供应商会将逻辑报价请求发送给所有逻辑提供程序。供应商接收到报价后,您可以看到会将最低报价发回给客户。您也可以验证每种情况中的上下文令牌。这有助于理解发送给每个逻辑提供程序的唯一上下文。

向 Microsoft 发送对本主题的评论。