Как обмениваться сообщениями с конечными точками WCF и приложениями очереди сообщений
Существующие приложения MSMQ можно интегрировать с приложениями Windows Communication Foundation (WCF), используя привязку интеграции MSMQ для преобразования сообщений MSMQ в сообщения WCF и наоборот. Это позволяет вызывать принимающие приложения MSMQ из клиентов WCF, а также вызывать службы WCF из отправляющих приложений MSMQ.
В этом разделе рассматривается, как использовать привязку MsmqIntegrationBinding для взаимодействия с использованием очередей между (1) клиентом WCF и службой приложения MSMQ, созданной с помощью System.Messaging, и (2) клиентом приложения MSMQ и службой WCF.
Полный пример, демонстрирующий вызов принимающего приложения MSMQ из клиента WCF, см. в примере Отправка сообщений из приложения Windows Communication Foundation в службу очередей сообщений.
Полный пример, демонстрирующий вызов службы WCF из клиента MSMQ, см. в примере Передача сообщений из службы очередей сообщений в приложение Windows Communication Foundation.
Создание службы WCF, получающей сообщения от клиента MSMQ
Определите интерфейс, который задает контракт службы для службы WCF, принимающей сообщения с использованием очередей от передающего приложения MSMQ, как показано в следующем примере кода.
<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); }
Реализуйте интерфейс и примените атрибут 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(); } } }
Создайте файл конфигурации, задающий привязку 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>
Создайте экземпляр объекта ServiceHost, использующий настроенную привязку.
Создание клиента WCF, передающего сообщения в принимающее приложение MSMQ
Определите интерфейс, который задает контракт службы для клиента WCF, передающего сообщения с использованием очередей в принимающее приложения MSMQ, как показано в следующем примере кода.
<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 { }
Определите класс клиента, используемый клиентом 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);
Создайте конфигурацию, которая задает использование привязки 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>
Создайте экземпляр класса клиента и вызовите метод, определенный службой приема сообщений.
// 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)