如何:与 WCF 终结点和消息队列应用程序交换消息

通过使用 MSMQ 集成绑定,可以将现有消息队列 (MSMQ) 应用程序与 Windows Communication Foundation (WCF) 应用程序进行集成,从而在 MSMQ 消息与 WCF 消息之间进行转换。利用这一功能,可以在 WCF 客户端调用 MSMQ 接收方应用程序,也可以在 MSMQ 发送方应用程序中调用 WCF 服务。

本节中,将说明如何将 MsmqIntegrationBinding 用于 (1) WCF 客户端和使用 System.Messaging 编写的 MSMQ 应用程序服务之间的排队通信,以及 (2) MSMQ 应用程序客户端和 WCF 服务之间的排队通信。

有关演示如何从 WCF 客户端调用 MSMQ 接收方应用程序的完整示例,请参见 Windows Communication Foundation 到消息队列示例。

有关演示如何从 MSMQ 客户端调用 WCF 服务的完整示例,请参见到 Windows Communication Foundation 的消息队列 示例。

创建从 MSMQ 客户端接收消息的 WCF 服务

  1. 定义一个接口,该接口为从 MSMQ 发送方应用程序接收排队消息的 WCF 服务定义服务协定,如下面的示例代码所示。

    <ServiceContract(Namespace:="http:'Microsoft.ServiceModel.Samples")> _
    <ServiceKnownType(GetType(PurchaseOrder))> _
    Public Interface IOrderProcessor
        <OperationContract(IsOneWay:=True, Action:="*")> _
        Sub SubmitPurchaseOrder(ByVal msg As MsmqMessage(Of PurchaseOrder))
    End Interface
    
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    [ServiceKnownType(typeof(PurchaseOrder))]
    public interface IOrderProcessor
    {
        [OperationContract(IsOneWay = true, Action = "*")]
        void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);
    }
    
  2. 实现该接口,将 ServiceBehaviorAttribute 属性应用于该类,如下面示例代码所示。

    Public Class OrderProcessorService
        Implements IOrderProcessor
    
        <OperationBehavior(TransactionScopeRequired:=True, TransactionAutoComplete:=True)> _
        Public Sub SubmitPurchaseOrder(ByVal ordermsg As MsmqMessage(Of PurchaseOrder)) Implements IOrderProcessor.SubmitPurchaseOrder
            Dim po As PurchaseOrder = ordermsg.Body
            Dim statusIndexer As New Random()
            po.Status = statusIndexer.Next(3)
            Console.WriteLine("Processing {0} ", po)
        End Sub
    End Class
    
    public class OrderProcessorService : IOrderProcessor
    {
        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> ordermsg)
        {
            PurchaseOrder po = (PurchaseOrder)ordermsg.Body;
            Random statusIndexer = new Random();
            po.Status = (OrderStates)statusIndexer.Next(3);
            Console.WriteLine("Processing {0} ", po);
        }
    
        // Host the service within this EXE console application.
    public static void Main()
    {
        // Get base address from appsettings in configuration.
        Uri baseAddress = new Uri(ConfigurationManager.AppSettings["baseAddress"]);
    
        // Create a ServiceHost for the CalculatorService type and provide the base address.
        using (ServiceHost serviceHost = new ServiceHost(typeof(IOrderProcessor), baseAddress))
        {
        // Open the ServiceHostBase to create listeners and start listening for messages.
            serviceHost.Open();
    
        // The service can now be accessed.
            Console.WriteLine("The service is ready.");
            Console.WriteLine("The service is running in the following account: {0}", WindowsIdentity.GetCurrent().Name);
            Console.WriteLine("Press <ENTER> to terminate service.");
            Console.WriteLine();
            Console.ReadLine();
    
        // Close the ServiceHostBase to shutdown the service.
            serviceHost.Close();
        }
    }
    
    }
    
  3. 创建一个配置文件,在该配置文件中指定 MsmqIntegrationBinding

    <configuration>
      <appSettings>
        <!-- use appSetting to configure MSMQ queue name -->
        <add key="orderQueueName" value=".\private$\Orders" />
        <add key="baseAddress" value="https://localhost:8000/ServiceModelSamples/Service" />
      </appSettings>
      <system.serviceModel>
        <services>
          <service 
            name="Microsoft.ServiceModel.Samples.OrderProcessorService" >
            <endpoint address="msmq.formatname:DIRECT=OS:.\private$\Orders"
                                    binding="msmqIntegrationBinding"
                      bindingConfiguration="OrderProcessorBinding" 
                      contract="Microsoft.ServiceModel.Samples.IOrderProcessor">
            </endpoint>
          </service>
        </services>
    
        <bindings>
          <msmqIntegrationBinding>
            <binding name="OrderProcessorBinding" >
              <security mode="None" />
            </binding>
          </msmqIntegrationBinding>
        </bindings>
    
      </system.serviceModel >
    
    </configuration>
    
  4. 实例化一个 ServiceHost 对象,该对象使用所配置的绑定。

创建向 MSMQ 接收方应用程序发送消息的 WCF 客户端

  1. 定义一个接口,该接口为向 MSMQ 接收方发送排队消息的 WCF 客户端定义服务协定,如下面的示例代码所示。

    <System.ServiceModel.ServiceContractAttribute(Namespace:="http:'Microsoft.ServiceModel.Samples")> _
    Public Interface IOrderProcessor
        <OperationContract(IsOneWay:=True, Action:="*")> _
        Sub SubmitPurchaseOrder(ByVal msg As MsmqMessage(Of PurchaseOrder))
    end interface
    
    Public Interface IOrderProcessorChannel
        Inherits IOrderProcessor, System.ServiceModel.IClientChannel
    End Interface
    
    [System.ServiceModel.ServiceContractAttribute(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface IOrderProcessor
    {
        [OperationContract(IsOneWay = true, Action = "*")]
        void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);
    }
    
    public interface IOrderProcessorChannel : IOrderProcessor, System.ServiceModel.IClientChannel
    {
    }
    
  2. 定义一个客户端类,WCF 客户端使用该类来调用 MSMQ 接收方。

    Dim binding As New MsmqIntegrationBinding()
    Dim address As New EndpointAddress("msmq.formatname:DIRECT=OS:.\\private$\\Orders")
    Dim channelFactory As New ChannelFactory(Of IOrderProcessor)(binding, address)
    Dim channel As IOrderProcessor = channelFactory.CreateChannel()
    
    Dim po As New PurchaseOrder()
    po.customerId = "somecustomer.com"
    po.poNumber = Guid.NewGuid().ToString()
    
    Dim lineItem1 As New PurchaseOrderLineItem()
    lineItem1.productId = "Blue Widget"
    lineItem1.quantity = 54
    lineItem1.unitCost = 29.99F
    
    Dim lineItem2 = New PurchaseOrderLineItem()
    lineItem2.productId = "Red Widget"
    lineItem2.quantity = 890
    lineItem2.unitCost = 45.89F
    
    Dim lineItems(2) As PurchaseOrderLineItem
    lineItems(0) = lineItem1
    lineItems(1) = lineItem2
    
    po.orderLineItems = lineItems
    
    Dim ordermsg As MsmqMessage(Of PurchaseOrder) = New MsmqMessage(Of PurchaseOrder)(po)
    Using scope As New TransactionScope(TransactionScopeOption.Required)
        channel.SubmitPurchaseOrder(ordermsg)
        scope.Complete()
    End Using
    Console.WriteLine("Order has been submitted:{0}", po)
    
    MsmqIntegrationBinding binding = new MsmqIntegrationBinding();
    EndpointAddress address = new EndpointAddress("msmq.formatname:DIRECT=OS:.\\private$\\Orders");
    ChannelFactory<IOrderProcessor> channelFactory = new ChannelFactory<IOrderProcessor>(binding, address);
    IOrderProcessor channel = channelFactory.CreateChannel();
    
    PurchaseOrder po = new PurchaseOrder();
    po.customerId = "somecustomer.com";
    po.poNumber = Guid.NewGuid().ToString();
    
    PurchaseOrderLineItem lineItem1 = new PurchaseOrderLineItem();
    lineItem1.productId = "Blue Widget";
    lineItem1.quantity = 54;
    lineItem1.unitCost = 29.99F;
    
    PurchaseOrderLineItem lineItem2 = new PurchaseOrderLineItem();
    lineItem2.productId = "Red Widget";
    lineItem2.quantity = 890;
    lineItem2.unitCost = 45.89F;
    
    po.orderLineItems = new PurchaseOrderLineItem[2];
    po.orderLineItems[0] = lineItem1;
    po.orderLineItems[1] = lineItem2;
    
    
    MsmqMessage<PurchaseOrder> ordermsg = new MsmqMessage<PurchaseOrder>(po);
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
    {
        channel.SubmitPurchaseOrder(ordermsg);
        scope.Complete();
    }
    Console.WriteLine("Order has been submitted:{0}", po);
    
  3. 创建一个配置文件,在该配置文件中指定 MsmqIntegrationBinding 绑定的用法。

    Dim binding As New MsmqIntegrationBinding("MyBindingConfig")
    
    MsmqIntegrationBinding binding = new MsmqIntegrationBinding("MyBindingConfig");
    
    <configuration>
        <system.serviceModel>
    
        <client>
          <endpoint  name="OrderResponseEndpoint" 
                    address="msmq.formatname:DIRECT=OS:.\private$\Orders"
                    binding="msmqIntegrationBinding"
                    bindingConfiguration="OrderProcessorBinding" 
                    contract="Microsoft.ServiceModel.Samples.IOrderProcessor">
          </endpoint>
        </client>
    
        <bindings>
          <msmqIntegrationBinding>
            <binding name="OrderProcessorBinding" >
              <security mode="None" />
            </binding>
          </msmqIntegrationBinding>
        </bindings>
    
      </system.serviceModel>
    
    </configuration>
    
  4. 创建该客户端类的一个实例,并调用消息接收服务所定义的方法。

    // Create the purchase order.
    PurchaseOrder po = new PurchaseOrder();
    po.customerId = "somecustomer.com";
    po.poNumber = Guid.NewGuid().ToString();
    
    PurchaseOrderLineItem lineItem1 = new PurchaseOrderLineItem();
    lineItem1.productId = "Blue Widget";
    lineItem1.quantity = 54;
    lineItem1.unitCost = 29.99F;
    
    PurchaseOrderLineItem lineItem2 = new PurchaseOrderLineItem();
    lineItem2.productId = "Red Widget";
    lineItem2.quantity = 890;
    lineItem2.unitCost = 45.89F;
    
    po.orderLineItems = new PurchaseOrderLineItem[2];
    po.orderLineItems[0] = lineItem1;
    po.orderLineItems[1] = lineItem2;
    
    OrderProcessorClient client = new OrderProcessorClient("OrderResponseEndpoint");
    MsmqMessage<PurchaseOrder> ordermsg = new MsmqMessage<PurchaseOrder>(po);
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
    {
        client.SubmitPurchaseOrder(ordermsg);
        scope.Complete();
    }
    
    Console.WriteLine("Order has been submitted:{0}", po);
    
    //Closing the client gracefully closes the connection and cleans up resources.
    client.Close();
    
    Console.WriteLine();
    Console.WriteLine("Press <ENTER> to terminate client.");
    Console.ReadLine();
    

另请参见

任务

如何:使用 WCF 终结点交换排队消息
Windows Communication Foundation 到消息队列
到 Windows Communication Foundation 的消息队列
基于消息队列的消息安全性

概念

队列概述
安装“消息队列 (MSMQ)”

其他资源

Message Queuing Integration Binding Samples