Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Exemplet MessageCorrelation visar hur ett MSMQ-program (Message Queuing) kan skicka ett MSMQ-meddelande till en WCF-tjänst (Windows Communication Foundation) och hur meddelanden kan korreleras mellan avsändare och mottagarprogram i ett begäran/svar-scenario. Det här exemplet använder bindningen msmqIntegrationBinding. Tjänsten i det här fallet är ett lokalt konsolprogram som gör att du kan observera tjänsten som tar emot köade meddelanden. k
Tjänsten bearbetar meddelandet som tas emot från avsändaren och skickar ett svarsmeddelande tillbaka till avsändaren. Avsändaren korrelerar det svar som den tog emot på den begäran som den ursprungligen skickade. Egenskaperna MessageID och CorrelationID för meddelandet används för att korrelera begärande- och svarsmeddelandena.
Tjänstkontraktet IOrderProcessor definierar en enkelriktad tjänstoperation som är lämplig för användning med köer. Ett MSMQ-meddelande har inget Åtgärds-huvud, så det går inte att mappa olika MSMQ-meddelanden till funktionskontrakt automatiskt. Därför kan det bara finnas ett åtgärdskontrakt i det här fallet. Om du vill definiera fler åtgärdskontrakt i tjänsten måste programmet ange information om vilket huvud i MSMQ-meddelandet (till exempel etiketten eller correlationID) som kan användas för att bestämma vilket åtgärdskontrakt som ska skickas.
MSMQ-meddelandet innehåller inte heller information om vilka rubriker som mappas till de olika parametrarna i åtgärdskontraktet. Därför kan det bara finnas en parameter i åtgärdskontraktet. Parametern är av typen MsmqMessage<T>, som innehåller det underliggande MSMQ-meddelandet. Typen "T" i MsmqMessage<T> klassen representerar de data som serialiseras i MSMQ-meddelandetexten. I det här exemplet serialiseras typen PurchaseOrder i MSMQ-meddelandetexten.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[ServiceKnownType(typeof(PurchaseOrder))]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true, Action = "*")]
void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);
}
Tjänståtgärden bearbetar inköpsordern och visar innehållet i inköpsordern och dess status i tjänstkonsolfönstret.
OperationBehaviorAttribute Konfigurerar åtgärden för att registrera en transaktion med kön och markera transaktionen som slutförd när åtgärden returneras.
PurchaseOrder Innehåller orderinformationen som måste bearbetas av tjänsten.
// 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();
}
}
Tjänsten använder en anpassad klient OrderResponseClient för att skicka MSMQ-meddelandet till kön. Eftersom programmet som tar emot och bearbetar meddelandet är ett MSMQ-program och inte ett WCF-program, finns det inget implicit tjänstkontrakt mellan de två programmen. Därför kan vi inte skapa en proxy med hjälp av verktyget Svcutil.exe i det här scenariot.
Den anpassade proxyn är i stort sett densamma för alla WCF-program som använder bindningen msmqIntegrationBinding för att skicka meddelanden. Till skillnad från andra proxyn inkluderar den inte olika tjänsteoperationer. Det är endast en skicka meddelandeåtgärd.
[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);
}
}
Tjänsten är lokalt installerad. När du använder MSMQ-integreringstransporten måste den kö som används skapas i förväg. Detta kan göras manuellt eller via kod. I det här exemplet innehåller System.Messaging tjänsten kod för att kontrollera om kön finns och skapa den om det behövs. Könamnet läses från konfigurationsfilen.
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();
}
}
DEN MSMQ-kö som orderbegäranden skickas till anges i avsnittet appSettings i konfigurationsfilen. Klient- och tjänstslutpunkterna definieras i avsnittet system.serviceModel i konfigurationsfilen. Båda anger bindningen 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>
Klientprogrammet använder System.Messaging för att skicka ett varaktigt och transaktionellt meddelande till kön. Meddelandets brödtext innehåller inköpsordern.
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...");
}
DEN MSMQ-kö från vilken ordersvaren tas emot anges i ett appInställningar-avsnitt i konfigurationsfilen, enligt följande exempelkonfiguration.
Anmärkning
Könamnet använder en punkt (.) för den lokala datorn och omvänt snedstrecksavgränsare i sökvägen. WCF-slutpunktsadressen anger ett msmq.formatname-schema och använder "localhost" för den lokala datorn. Ett korrekt formatnamn följer msmq.formatname i URI:n enligt MSMQ-riktlinjerna.
<appSettings>
<add key=" orderResponseQueueName" value=".\private$\Orders" />
</appSettings>
Klientprogrammet sparar orderbegärandemeddelandet messageID som skickas till tjänsten och väntar på ett svar från tjänsten. När ett svar anländer i kön, korrelerar klienten det med ordermeddelandet det skickade, genom att använda meddelandets correlationID-egenskap, som innehåller messageID av ordermeddelandet som klienten ursprungligen skickade till tjänsten.
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);
}
}
}
När du kör exemplet visas klient- och tjänstaktiviteterna i både tjänst- och klientkonsolfönstren. Du kan se att tjänsten tar emot meddelanden från klienten och skickar ett svar tillbaka till klienten. Klienten visar svaret som tagits emot från tjänsten. Tryck på RETUR i varje konsolfönster för att stänga av tjänsten och klienten.
Anmärkning
Det här exemplet kräver installation av Message Queuing (MSMQ). Se installationsanvisningarna för MSMQ i avsnittet Se även.
Konfigurera, skapa och köra exemplet
Kontrollera att du har utfört One-Time installationsproceduren för Windows Communication Foundation-exempel.
Om tjänsten körs först kontrollerar den att kön finns. Om kön inte finns skapar tjänsten en. Du kan köra tjänsten först för att skapa kön, eller så kan du skapa en via MSMQ Queue Manager. Följ de här stegen för att skapa en kö i Windows 2008.
Öppna Serverhanteraren i Visual Studio 2012.
Expandera fliken Funktioner.
Högerklicka på privata meddelandeköeroch välj Ny, privat kö.
Markera kryssrutan Transactional.
Ange
ServiceModelSamplesTransactedsom namnet på den nya kön.
Om du vill skapa C# eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel.
Om du vill köra exemplet i en konfiguration med en enda dator följer du anvisningarna i Köra Windows Communication Foundation-exempel.
Kör exemplet mellan datorer
Kopiera tjänstprogramfilerna från mappen \service\bin\ under den språkspecifika mappen till tjänstdatorn.
Kopiera klientprogramfilerna från mappen \client\bin\ under den språkspecifika mappen till klientdatorn.
I filen Client.exe.config ändrar du orderQueueName så att namnet på tjänstdatorn anges i stället för "".
I filen Service.exe.config ändrar du klientens slutpunktsadress för att ange klientdatorns namn i stället för "".
Starta Service.exe från en kommandotolk på tjänstdatorn.
Starta Client.exe från en kommandoprompt på klientdatorn.