このサンプルでは、メッセージ キュー (MSMQ) アプリケーションで MSMQ メッセージを Windows Communication Foundation (WCF) サービスに送信する方法と、要求または応答のシナリオで、メッセージを送信側のアプリケーションと受信側のアプリケーション間で相互に関連付ける方法を示します。このサンプルでは、msmqIntegrationBinding バインディングを使用します。この場合、サービスは自己ホスト型コンソール アプリケーションで、サービスがキュー内のメッセージを受信したかどうかを監視できます。
サービスは、送信側からの受信メッセージを処理し、送信側に応答メッセージを返信します。送信側は、受信した応答を、最初に送信した要求に関連付けます。メッセージの MessageID プロパティと CorrelationID プロパティを使用すると、要求メッセージと応答メッセージが関連付けられます。
IOrderProcessor
サービス コントラクトは、キューでの使用に適した一方向サービス操作を定義します。MSMQ メッセージには Action ヘッダーがないので、さまざまな MSMQ メッセージを操作コントラクトに自動的にマッピングすることはできません。したがってこの場合、存在する操作コントラクトは 1 つだけです。サービス内に複数の操作コントラクトを定義する場合は、ディスパッチする操作コントラクトを決定するために使用できる、MSMQ メッセージ内のヘッダー (ラベルや correlationID など) に関する情報をアプリケーションで提供する必要があります。これについては、「カスタム Demux」を参照してください。
さらに、MSMQ メッセージには、操作コントラクトの別のパラメータにマッピングされるヘッダーに関する情報は含まれません。したがって、操作コントラクトに存在するパラメータは 1 つだけです。パラメータは MsmqMessage 型の MsmqMessage<T> です。これには、基になる MSMQ メッセージが含まれます。MsmqMessage<T> クラスの型 "T" は、シリアル化されて MSMQ メッセージ本文に含まれているデータを表します。このサンプルでは、PurchaseOrder
型がシリアル化されて MSMQ メッセージ本文になっています。
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[ServiceKnownType(typeof(PurchaseOrder))]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true, Action = "*")]
void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);
}
このサービス操作は発注書を処理し、サービス コンソール ウィンドウにその発注書の内容と状態を表示します。OperationBehaviorAttribute はこの操作を構成してキューを伴うトランザクションに登録し、操作が返されたときにトランザクションに完了とマークします。PurchaseOrder
には、サービスで処理する必要のある発注の詳細が含まれています。
// Service class that implements the service contract.
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 = PurchaseOrder.OrderStates[statusIndexer.Next(3)];
Console.WriteLine("Processing {0} ", po);
//Send a response to the client that the order has been received
and is pending fullfillment.
SendResponse(ordermsg);
}
private void SendResponse(MsmqMessage<PurchaseOrder> ordermsg)
{
OrderResponseClient client = new OrderResponseClient("OrderResponseEndpoint");
//Set the correlation ID such that the client can correlate the response to the order.
MsmqMessage<PurchaseOrder> orderResponsemsg = new MsmqMessage<PurchaseOrder>(ordermsg.Body);
orderResponsemsg.CorrelationId = ordermsg.Id;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
client.SendOrderResponse(orderResponsemsg);
scope.Complete();
}
client.Close();
}
}
サービスは、MSMQ メッセージをキューに送信するためにカスタム クライアント OrderResponseClient
を使用します。メッセージを受信して処理するアプリケーションが MSMQ アプリケーションであり、WCF アプリケーションではないので、2 つのアプリケーション間で暗黙のサービス コントラクトはありません。したがって、このシナリオでは Svcutil.exe ツールを使用してプロキシを作成することはできません。
カスタム プロキシは基本的に、msmqIntegrationBinding バインディングを使用してメッセージを送信するすべての WCF アプリケーションで同じです。他のプロキシと異なり、サービス操作の範囲は含まれません。メッセージ送信操作のみです。
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface IOrderResponse
{
[System.ServiceModel.OperationContractAttribute(IsOneWay = true, Action = "*")]
void SendOrderResponse(MsmqMessage<PurchaseOrder> msg);
}
public partial class OrderResponseClient : System.ServiceModel.ClientBase<IOrderResponse>, IOrderResponse
{
public OrderResponseClient()
{ }
public OrderResponseClient(string configurationName)
: base(configurationName)
{ }
public OrderResponseClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress address)
: base(binding, address)
{ }
public void SendOrderResponse(MsmqMessage<PurchaseOrder> msg)
{
base.Channel.SendOrderResponse(msg);
}
}
サービスは自己ホスト型です。MSMQ 統合トランスポートを使用する場合、使用するキューをあらかじめ作成しておく必要があります。手動で作成することもコードで作成することもできます。このサンプルでは、キューの存在を確認して、必要な場合は作成するための System.Messaging コードがサービスに含まれています。キュー名は構成ファイルから読み込まれます。
public static void Main()
{
// Get the MSMQ queue name from application settings in configuration.
string queueName =
ConfigurationManager.AppSettings["orderQueueName"];
// 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)))
{
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
// Close the ServiceHost to shutdown the service.
serviceHost.Close();
}
}
発注要求が送信される MSMQ キューは、構成ファイルの appSettings セクションで指定されます。クライアントおよびサービスのエンドポイントは、構成ファイルの system.serviceModel セクションで定義されます。どちらも msmqIntegrationbinding バインディングを指定します。
<appSettings>
<add key="orderQueueName" value=".\private$\Orders" />
</appSettings>
<system.serviceModel>
<client>
<endpoint name="OrderResponseEndpoint"
address="msmq.formatname:DIRECT=OS:.\private$\OrderResponse"
binding="msmqIntegrationBinding"
bindingConfiguration="OrderProcessorBinding"
contract="Microsoft.ServiceModel.Samples.IOrderResponse">
</endpoint>
</client>
<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>
クライアント アプリケーションは System.Messaging を使用して、非揮発性メッセージとトランザクション メッセージをキューに送信します。メッセージの本文には発注書が含まれます。
static void PlaceOrder()
{
//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;
Message msg = new Message();
msg.UseDeadLetterQueue = true;
msg.Body = po;
//Create a transaction scope.
using (TransactionScope scope = new
TransactionScope(TransactionScopeOption.Required))
{
// Submit the purchase order.
orderQueue.Send(msg, MessageQueueTransactionType.Automatic);
// Complete the transaction.
scope.Complete();
}
//Save the messageID for order response correlation.
orderMessageID = msg.Id;
Console.WriteLine("Placed the order, waiting for response...");
}
発注の応答を受信する MSMQ キューは、構成ファイルの appSettings セクションで指定されます。次のサンプル構成を参照してください。
![]() |
---|
キューの名前では、ローカル コンピュータにはドット (.) が使用され、パスの区切りにはバックスラッシュが使用されます。WCF エンドポイント アドレスでは msmq.formatname スキームが指定され、ローカル コンピュータには "localhost" が使用されます。URI の msmq.formatname の後には、MSMQ ガイドラインに沿って正しく書式設定された形式名が続きます。 |
<appSettings>
<add key=" orderResponseQueueName" value=".\private$\Orders" />
</appSettings>
クライアント アプリケーションは、サービスに送信する発注要求メッセージの messageID を保存し、サービスからの応答を待機します。応答がキューに到着すると、クライアントは発注メッセージの correlationID プロパティを使用して、送信した発注メッセージと応答を関連付けます。このプロパティには、クライアントが最初にサービスに送信した発注メッセージの messageID が含まれています。
static void DisplayOrderStatus()
{
MessageQueue orderResponseQueue = new
MessageQueue(ConfigurationManager.AppSettings
["orderResponseQueueName"]);
//Create a transaction scope.
bool responseReceived = false;
orderResponseQueue.MessageReadPropertyFilter.CorrelationId = true;
while (!responseReceived)
{
Message responseMsg;
using (TransactionScope scope2 = new
TransactionScope(TransactionScopeOption.Required))
{
//Receive the Order Response message.
responseMsg =
orderResponseQueue.Receive
(MessageQueueTransactionType.Automatic);
scope2.Complete();
}
responseMsg.Formatter = new
System.Messaging.XmlMessageFormatter(new Type[] {
typeof(PurchaseOrder) });
PurchaseOrder responsepo = (PurchaseOrder)responseMsg.Body;
//Check if the response is for the order placed.
if (orderMessageID == responseMsg.CorrelationId)
{
responseReceived = true;
Console.WriteLine("Status of current Order: OrderID-{0},Order
Status-{1}", responsepo.PONumber, responsepo.Status);
}
else
{
Console.WriteLine("Status of previous Order: OrderID-{0},Order
Status-{1}", responsepo.PONumber, responsepo.Status);
}
}
}
サンプルを実行すると、クライアントとサービスのアクティビティがサービスとクライアントの両方のコンソール ウィンドウに表示されます。サービスがクライアントからメッセージを受信し、クライアントに応答を返信するアクティビティを参照できます。クライアントでは、サービスから受信した応答が表示されます。どちらかのコンソールで Enter キーを押すと、サービスとクライアントがどちらもシャットダウンされます。
![]() |
---|
このサンプルを実行するには、メッセージ キュー (MSMQ) がインストールされている必要があります。インストールの手順については、「参照」セクションを参照してください。 |
サンプルをセットアップ、作成、および実行するには
「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」が実行済みであることを確認します。
ソリューションの C# 版または Visual Basic .NET 版をビルドするには、「Windows Communication Foundation サンプルのビルド」の手順に従います。
単一コンピュータ構成でサンプルを実行するには、「Windows Communication Foundation サンプルの実行」の手順に従います。
サンプルを別のコンピュータで実行するには
サービス プログラム ファイルを、言語固有のフォルダにある \service\bin\ フォルダからサービス コンピュータにコピーします。
クライアント プログラム ファイルを、言語固有のフォルダにある \client\bin\ フォルダからクライアント コンピュータにコピーします。
Client.exe.config ファイルで、orderQueueName を変更して "." の代わりにサービス コンピュータを指定します。
Service.exe.config ファイルで、クライアント エンドポイントのアドレスを変更して "." の代わりにクライアント コンピュータを指定します。
サービス コンピュータで、コマンド プロンプトから Service.exe を起動します。
クライアント コンピュータで、コマンド プロンプトから Client.exe を起動します。
関連項目
その他の技術情報
Copyright © 2007 by Microsoft Corporation.All rights reserved.