MsmqToWcf 示例演示消息队列 (MSMQ) 应用程序如何将 MSMQ 消息发送到 Windows Communication Foundation (WCF) 服务。 此服务是自承载控制台应用程序,通过它可以观察服务接收排队消息。
服务协定是IOrderProcessor
,它定义了一种适合用于队列的单向服务。 MSMQ 消息没有 Action 标头,因此无法自动将不同的 MSMQ 消息映射到作协定。 因此,只能有一个操作合同。 如果想为服务定义多个操作契约,应用程序必须提供关于 MSMQ 消息中哪个标头(例如,标签或 correlationID)可用于决定调度哪个操作契约的信息。
MSMQ 消息不包含关于哪些标头映射到操作契约的不同参数的信息。 该参数属于 MsmqMessage<T>(MsmqMessage<T>
) 类型,包含基础 MSMQ 消息。
MsmqMessage<T>(MsmqMessage<T>
) 类中的“T”类型代表序列化到 MSMQ 消息正文中的数据。 在此示例中,PurchaseOrder
类型已被序列化到 MSMQ 消息正文中。
以下示例代码显示了订单处理服务的服务协定。
// Define a service contract.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[ServiceKnownType(typeof(PurchaseOrder))]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true, Action = "*")]
void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);
}
该服务是自托管的。 使用 MSMQ 时,必须提前创建使用的队列。 这可以手动或通过代码完成。 在此示例中,服务会检查队列是否存在,并根据需要创建队列。 队列名称从配置文件中读取。
public static void Main()
{
// Get the MSMQ queue name from the application settings in
// configuration.
string queueName = ConfigurationManager.AppSettings["queueName"];
// Create the MSMQ queue if necessary.
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);
…
}
该服务为 ServiceHost 创建和打开 OrderProcessorService
,如下面的示例代码所示。
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService)))
{
serviceHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
serviceHost.Close();
}
MSMQ 队列名称是在配置文件的 appSettings 部分中指定的,如以下示例配置所示。
注释
队列名称为本地计算机使用圆点 (.),并在其路径中使用反斜杠分隔符。 WCF 终结点地址指定 msmq.formatname 方案,并将 localhost 用于本地计算机。 每个 MSMQ 格式名称寻址准则的队列地址遵循 msmq.formatname 方案。
<appSettings>
<add key="orderQueueName" value=".\private$\Orders" />
</appSettings>
客户端应用程序是一个 MSMQ 应用程序,它使用 Send 该方法将持久消息和事务性消息发送到队列,如以下示例代码所示。
//Connect to the queue.
MessageQueue orderQueue = new MessageQueue(ConfigurationManager.AppSettings["orderQueueName"]);
// 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;
// Submit the purchase order.
Message msg = new Message();
msg.Body = po;
//Create a transaction scope.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
orderQueue.Send(msg, MessageQueueTransactionType.Automatic);
// Complete the transaction.
scope.Complete();
}
Console.WriteLine("Placed the order:{0}", po);
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
运行示例时,客户端和服务活动会显示在服务和客户端控制台窗口中。 可以看到服务从客户端接收消息。 在每个控制台窗口中按 Enter 可以关闭服务和客户端。 请注意:由于正在使用队列,因此不必同时启动和运行客户端和服务。 例如,可以运行客户端,将其关闭,然后启动服务,但仍会收到其消息。
设置、生成和运行示例
确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。
如果先运行服务,则它将检查以确保队列存在。 如果队列不存在,服务将创建一个队列。 可以先运行服务来创建队列,也可以通过 MSMQ 队列管理器创建一个队列。 按照以下步骤在 Windows 2008 中创建队列。
在 Visual Studio 2012 中打开服务器管理器。
展开“功能”选项卡。
右键单击 专用消息队列,然后选择 “新建”,专用队列。
选中“事务性”框。
输入
ServiceModelSamplesTransacted
作为新队列的名称。
若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。
若要在单台计算机配置中运行示例,请按照《运行 Windows Communication Foundation 示例》中的说明进行操作。
在多台计算机上运行示例
将 \service\bin\ 文件夹中的服务程序文件(在语言特定的文件夹下)复制到服务计算机。
将 \client\bin\ 文件夹中的客户端程序文件(在特定于语言的文件夹下)复制到客户端计算机。
在 Client.exe.config 文件中,更改 orderQueueName 以指定服务计算机名称,而不是使用“.”。
在服务计算机上,从命令提示符启动 Service.exe。
在客户端计算机上,在命令提示符下启动 Client.exe。