Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
A MessageCorrelation minta bemutatja, hogy egy Message Queuing (MSMQ) alkalmazás hogyan küldhet MSMQ-üzenetet egy Windows Communication Foundation (WCF) szolgáltatásnak, és hogyan lehet korrelálni az üzeneteket a feladó és a fogadó alkalmazás között egy kérés/válasz forgatókönyvben. Ez a minta az msmqIntegrationBinding kötést használja. Ebben az esetben a szolgáltatás egy saját üzemeltetésű konzolalkalmazás, amely lehetővé teszi az üzenetsorba helyezett üzeneteket fogadó szolgáltatás megfigyelését. k
A szolgáltatás feldolgozza a feladótól kapott üzenetet, és visszaküld egy válaszüzenetet a feladónak. A feladó az általa eredetileg elküldött kérésre kapott választ korrelálja. Az MessageID és CorrelationID üzenet tulajdonságai a kérés- és válaszüzenetek korrelációjára szolgálnak.
A IOrderProcessor szolgáltatási szerződés egy egyirányú szolgáltatásműveletet határoz meg, amely alkalmas a sorba állításra. Az MSMQ-üzenetek nem rendelkeznek műveletfejléccel, így nem lehet különböző MSMQ-üzeneteket automatikusan hozzárendelni a műveleti szerződésekhez. Ezért ebben az esetben csak egy műveleti szerződés lehet. Ha további műveleti szerződéseket szeretne definiálni a szolgáltatásban, az alkalmazásnak meg kell adnia az MSMQ-üzenetben szereplő fejlécet (például a címkét vagy a korrelációs azonosítót) annak eldöntéséhez, hogy melyik műveleti szerződést küldje el.
Az MSMQ-üzenet azt sem tartalmazza, hogy mely fejlécek vannak leképezve a műveleti szerződés különböző paramétereihez. Ezért a műveleti szerződésben csak egy paraméter szerepelhet. A paraméter típusa MsmqMessage<T>a mögöttes MSMQ-üzenetet tartalmazza. Az osztály "T" típusa az MsmqMessage<T> MSMQ-üzenettörzsbe szerializált adatokat jelöli. Ebben a mintában a PurchaseOrder típus szerializálva lesz az MSMQ üzenettörzsében.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[ServiceKnownType(typeof(PurchaseOrder))]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true, Action = "*")]
void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);
}
A szolgáltatásművelet feldolgozza a vásárlási rendelést, és megjeleníti a vásárlási rendelés tartalmát és állapotát a szolgáltatáskonzol ablakában. A OperationBehaviorAttribute művelet úgy konfigurálja a műveletet, hogy a várólistával rendelkező tranzakcióba lépjen be, és hogy a művelet visszatérésekor a tranzakció befejezettként legyen megjelölve. Ez PurchaseOrder tartalmazza a szolgáltatás által feldolgozandó rendelési adatokat.
// 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 fulfillment.
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();
}
}
A szolgáltatás egy egyéni ügyfél OrderResponseClient használatával küldi el az MSMQ-üzenetet az üzenetsorba. Mivel az üzenetet fogadó és feldolgozó alkalmazás nem WCF-alkalmazás, hanem MSMQ-alkalmazás, a két alkalmazás között nincs implicit szolgáltatási szerződés. Ezért ebben a forgatókönyvben nem tudunk proxyt létrehozni a Svcutil.exe eszközzel.
Az egyéni proxy lényegében ugyanaz az összes WCF-alkalmazás esetében, amely a kötést használja az msmqIntegrationBinding üzenetek küldésére. A többi proxytól eltérően nem tartalmaz szolgáltatásműveleteket. Csak küldési üzenet művelet.
[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);
}
}
A szolgáltatás saját üzemeltetésű. Az MSMQ integrációs átvitel használatakor a használt üzenetsort előre létre kell hozni. Ez manuálisan vagy kódon keresztül is elvégezhető. Ebben a mintában a szolgáltatás System.Messaging kódot tartalmaz az üzenetsor meglétének ellenőrzéséhez és szükség esetén annak létrehozásához. A sor nevét a konfigurációs fájlból olvassák be.
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();
}
}
A rendelési kérelmeket küldő MSMQ-üzenetsor a konfigurációs fájl AppSettings szakaszában van megadva. Az ügyfél- és szolgáltatásvégpontok a konfigurációs fájl system.serviceModel szakaszában vannak definiálva. Mindkettő a msmqIntegrationBinding kötést adja meg.
<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>
Az ügyfélalkalmazás System.Messaging tartós és tranzakciós üzenetet küld az üzenetküldési sorba. Az üzenet törzse tartalmazza a megrendelést.
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...");
}
Az MSMQ-üzenetsor, amelyből a rendelési válaszok érkeznek, a konfigurációs fájl AppSettings szakaszában van megadva, ahogyan az az alábbi mintakonfigurációban látható.
Megjegyzés:
Az sor neve pontot (.) használ a helyi számítógéphez, és perjeleket az elérési útvonalában. A WCF végpontcíme egy msmq.formatname sémát határoz meg, és a helyi számítógéphez a "localhost" nevet használja. A megfelelően formázott formátumnév az msmq.formatname nevet követi az URI-ban az MSMQ-irányelveknek megfelelően.
<appSettings>
<add key=" orderResponseQueueName" value=".\private$\Orders" />
</appSettings>
Az ügyfélalkalmazás menti a messageID szolgáltatásnak küldött megrendeléskérési üzenetet, és megvárja a szolgáltatás válaszát. Amint egy válasz megérkezik az üzenetsorba, az ügyfél korrelálja azt a küldött megrendelési üzenettel az üzenet correlationID tulajdonságának segítségével, amely tartalmazza az ügyfél által eredetileg a szolgáltatásnak küldött megrendelési üzenet messageID-t.
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);
}
}
}
A minta futtatásakor az ügyfél- és szolgáltatástevékenységek a szolgáltatás és az ügyfélkonzol ablakaiban is megjelennek. Láthatja, hogy a szolgáltatás üzeneteket fogad az ügyféltől, és választ küld az ügyfélnek. Az ügyfél megjeleníti a szolgáltatástól kapott választ. A szolgáltatás és az ügyfél leállításához nyomja le az ENTER billentyűt az egyes konzolablakokban.
Megjegyzés:
Ehhez a mintához a Message Queuing (MSMQ) telepítése szükséges. Tekintse meg az MSMQ telepítési utasításait a Lásd még szakaszban.
A minta beállítása, összeállítása és futtatása
Győződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták One-Time beállítási eljárását.
Ha a szolgáltatást először futtatják, ellenőrzi, hogy az üzenetsor jelen van-e. Ha az üzenetsor nincs jelen, a szolgáltatás létrehoz egyet. Először futtathatja a szolgáltatást az üzenetsor létrehozásához, vagy létrehozhat egyet az MSMQ Queue Manageren keresztül. Az alábbi lépéseket követve hozzon létre egy sort a Windows Server 2008-ban.
Nyissa meg a Kiszolgálókezelőt a Visual Studio 2012-ben.
Nyissa meg a Funkciók lapot.
Kattintson a jobb gombbal a Privát üzenetsorokelemre, és válassza Új, Privát üzenetsorlehetőséget.
Jelölje be a Tranzakciós jelölőnégyzetet.
Adja meg
ServiceModelSamplesTransactedaz új üzenetsor neveként.
A megoldás C# vagy Visual Basic .NET kiadásának létrehozásához kövesse Windows Communication Foundation-mintákcímű témakör utasításait.
A minta egyszámítógépes konfigurációban való futtatásához kövesse a Windows Communication Foundation-minták futtatására vonatkozó utasításokat.
A minta futtatása számítógépeken
Másolja a szolgáltatásprogram fájljait a \service\bin\ mappából a nyelvspecifikus mappából a szolgáltatásszámítógépre.
Másolja az ügyfélprogram fájljait a \client\bin\ mappából a nyelvspecifikus mappából az ügyfélszámítógépre.
A Client.exe.config fájlban módosítsa az orderQueueName nevet úgy, hogy a "." helyett a szolgáltatásszámítógép nevét adja meg.
A Service.exe.config fájlban módosítsa az ügyfélvégpont címét úgy, hogy a "." helyett az ügyfélszámítógép nevét adja meg.
A szolgáltatásszámítógépen indítsa el a Service.exe parancssorból.
Az ügyfélszámítógépen indítsa el a Client.exe parancssorból.