Two-Way 範例示範如何透過 MSMQ 執行雙向佇列通訊。 這個範例會使用netMsmqBinding綁定。 在此情況下,服務是自我裝載的控制台應用程式,可讓您觀察接收佇列訊息的服務。
備註
此範例的安裝程式和建置指示位於本主題結尾。
此範例是以 具交易的 MSMQ 繫結為基礎。
在佇列通訊中,用戶端會使用佇列與服務通訊。 用戶端會將訊息傳送至佇列,而服務會接收來自佇列的訊息。 因此,服務與用戶端不需要同時執行,即可使用佇列進行通訊。
此範例示範使用佇列的雙向通訊。 用戶端會從交易範圍內,將採購單傳送至佇列。 服務在交易範圍內接收訂單、處理訂單,然後通知客戶訂單在佇列中的狀態。 為了提供雙向通訊便利,客戶端和服務端都會使用佇列來加入採購單和跟蹤訂單狀態。
服務合約 IOrderProcessor 會定義適合使用佇列的單向服務作業。 服務作業包含用來傳送訂單狀態的回復端點。 回復端點是佇列的 URI,用來將訂單狀態傳回用戶端。 訂單處理應用程式會實作此合約。
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true)]
void SubmitPurchaseOrder(PurchaseOrder po, string
reportOrderStatusTo);
}
傳送訂單狀態的回復合約是由用戶端所指定。 用戶端會實作訂單狀態合約。 服務會使用此合約產生的 Proxy,將訂單狀態傳回用戶端。
[ServiceContract]
public interface IOrderStatus
{
[OperationContract(IsOneWay = true)]
void OrderStatus(string poNumber, string status);
}
服務作業會處理提交的採購單。
OperationBehaviorAttribute應用於服務作業,以指定在交易中的自動參與,該交易用來接收佇列的訊息,並在服務作業完成時自動完成交易。 類別 Orders 會封裝訂單處理功能。 在此情況下,它會將採購單新增至字典。 服務作業所登記的交易可供 類別中的 Orders 作業使用。
除了處理提交的採購單外,服務作業也會回復用戶端訂單的狀態。
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SubmitPurchaseOrder(PurchaseOrder po, string reportOrderStatusTo)
{
Orders.Add(po);
Console.WriteLine("Processing {0} ", po);
Console.WriteLine("Sending back order status information");
NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding("ClientCallbackBinding");
OrderStatusClient client = new OrderStatusClient(msmqCallbackBinding, new EndpointAddress(reportOrderStatusTo));
// Please note that the same transaction that is used to dequeue the purchase order is used
// to send back order status.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
client.OrderStatus(po.PONumber, po.Status);
scope.Complete();
}
//Close the client.
client.Close();
}
MSMQ 佇列名稱是在組態檔的 appSettings 區段中指定。 服務的端點定義於組態檔的 System.ServiceModel 區段中。
備註
MSMQ 佇列名稱和端點位址會使用稍微不同的尋址慣例。 MSMQ 佇列名稱會使用點(.)來表示本機電腦,並在路徑中使用反斜線作為分隔符。 Windows Communication Foundation(WCF)端點位址指定為 net.msmq:方案,使用 "localhost" 表示本機計算機,並在路徑中使用正斜線。 若要從遠端電腦上裝載的佇列讀取,請將 “.” 和 “localhost” 取代為遠端電腦名稱。
服務是自我托管的。 使用 MSMQ 傳輸時,必須事先建立所使用的佇列。 這可以手動或透過程式代碼來完成。 在此範例中,服務會檢查佇列是否存在,並視需要建立佇列。 佇列名稱會從組態檔讀取。 ServiceModel 元數據公用程式工具 (Svcutil.exe) 會使用基地址來產生服務的 Proxy。
// Host the service within this EXE console application.
public static void Main()
{
// Get MSMQ queue name from appSettings in configuration.
string queueName = ConfigurationManager.AppSettings["queueName"];
// Create the transacted MSMQ queue if necessary.
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);
// Create a ServiceHost for the OrderProcessorService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService)))
{
// Open the ServiceHost to create listeners and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
}
用戶端會建立交易。 與佇列的通訊會在交易的範疇內進行,這使得它被視為一個不可分割的單元,所有訊息要麼全部成功,要麼全部失敗。
// Create a ServiceHost for the OrderStatus service type.
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderStatusService)))
{
// Open the ServiceHostBase to create listeners and start listening for order status messages.
serviceHost.Open();
// Create the purchase order.
...
// Create a client with given client endpoint configuration.
OrderProcessorClient client = new OrderProcessorClient("OrderProcessorEndpoint");
//Create a transaction scope.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
string hostName = Dns.GetHostName();
// Make a queued call to submit the purchase order.
client.SubmitPurchaseOrder(po, "net.msmq://" + hostName + "/private/ServiceModelSamplesTwo-way/OrderStatus");
// Complete the transaction.
scope.Complete();
}
//Close down the client.
client.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
// Close the ServiceHost to shutdown the service.
serviceHost.Close();
}
用戶端程式代碼會實作 IOrderStatus 合約,以從服務接收訂單狀態。 在此情況下,它會列印訂單狀態。
[ServiceBehavior]
public class OrderStatusService : IOrderStatus
{
[OperationBehavior(TransactionAutoComplete = true,
TransactionScopeRequired = true)]
public void OrderStatus(string poNumber, string status)
{
Console.WriteLine("Status of order {0}:{1} ", poNumber ,
status);
}
}
順序狀態佇列是在 方法中 Main 建立的。 用戶端組態包含用來裝載訂單狀態服務的訂單狀態服務組態,如下列範例組態所示。
<appSettings>
<!-- Use appSetting to configure MSMQ queue name. -->
<add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderStatus" />
</appSettings>
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.OrderStatusService">
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderStatus"
binding="netMsmqBinding"
contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
</service>
</services>
<client>
<!-- Define NetMsmqEndpoint -->
<endpoint name="OrderProcessorEndpoint"
address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor"
binding="netMsmqBinding"
contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
</client>
</system.serviceModel>
當您執行範例時,用戶端和服務活動會顯示在服務和用戶端控制台視窗中。 您可以看到服務從用戶端接收訊息。 在每個主控台視窗中按 ENTER 鍵,關閉服務和用戶端。
服務會顯示採購單資訊,並指出它正在將訂單狀態傳回至訂單狀態佇列。
The service is ready.
Press <ENTER> to terminate service.
Processing Purchase Order: 124a1f69-3699-4b16-9bcc-43147a8756fc
Customer: somecustomer.com
OrderDetails
Order LineItem: 54 of Blue Widget @unit price: $29.99
Order LineItem: 890 of Red Widget @unit price: $45.89
Total cost of this order: $42461.56
Order status: Pending
Sending back order status information
用戶端會顯示服務傳送的訂單狀態資訊。
Press <ENTER> to terminate client.
Status of order 124a1f69-3699-4b16-9bcc-43147a8756fc:Pending
要設定、建置和執行範例,請執行以下步驟:
請確定您已針對 Windows Communication Foundation 範例 執行One-Time 安裝程式。
若要建置解決方案的 C# 或 Visual Basic .NET 版本,請遵循建置 Windows Communication Foundation 範例 中中的指示。
若要在單一或跨計算機組態中執行範例,請遵循執行 Windows Communication Foundation 範例 中的指示。
備註
如果您使用 Svcutil.exe 重新產生此範例的組態,請務必修改用戶端組態中的端點名稱,以符合客戶端程序代碼。
根據預設, NetMsmqBinding會啟用傳輸安全性。 MSMQ 傳輸安全性有兩個相關屬性,MsmqAuthenticationMode 和 MsmqProtectionLevel.。根據預設,驗證模式會設定為 Windows,並且保護層級會設定為 Sign。 若要讓 MSMQ 提供驗證和簽署功能,它必須是網域的一部分,而且必須安裝 MSMQ 的 Active Directory 整合選項。 如果您在不符合這些準則的計算機上執行此範例,您會收到錯誤。
若要在加入工作組的電腦或尚未整合 Active Directory 的電腦上執行範例
如果您的計算機不是網域的一部分,或未安裝 Active Directory 整合,請將驗證模式和保護層級設定為
None來關閉傳輸安全性,如下列範例組態所示:<configuration> <appSettings> <!-- Use appSetting to configure MSMQ queue name. --> <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderProcessor" /> </appSettings> <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.OrderProcessorService"> <!-- Define NetMsmqEndpoint --> <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="Microsoft.ServiceModel.Samples.IOrderProcessor" /> </service> </services> <bindings> <netMsmqBinding> <binding name="TransactedBinding" > <security mode="None" /> </binding> </netMsmqBinding> </bindings> </system.serviceModel> </configuration>關閉客戶端設定的安全性會產生以下內容:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <!-- Use appSetting to configure MSMQ queue name. --> <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderStatus" /> </appSettings> <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.OrderStatusService"> <!-- Define NetMsmqEndpoint --> <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderStatus" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="Microsoft.ServiceModel.Samples.IOrderStatus" /> </service> </services> <client> <!-- Define NetMsmqEndpoint --> <endpoint name="OrderProcessorEndpoint" address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="Microsoft.ServiceModel.Samples.IOrderProcessor" /> </client> <bindings> <netMsmqBinding> <binding name="TransactedBinding" > <security mode="None" /> </binding> </netMsmqBinding> </bindings> </system.serviceModel> </configuration>此範例的服務會在
OrderProcessorService中建立系結。 在具現化系結之後新增一行程式代碼,將安全性模式設定為None。NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding(); msmqCallbackBinding.Security.Mode = NetMsmqSecurityMode.None;在執行範例之前,請確定您已在伺服器和用戶端上變更組態。
備註
設定
security mode為None相當於設定MsmqAuthenticationMode、MsmqProtectionLevel或Message的安全性為None。