Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Das Session-Beispiel veranschaulicht, wie ein Satz zusammengehöriger Nachrichten bei der Kommunikation unter Verwendung von Warteschlangen über den MSMQ-Transport (Message Queuing) gesendet und empfangen wird. In diesem Beispiel wird die netMsmqBinding Bindung verwendet. Der Dienst ist eine selbst gehostete Konsolenanwendung, mit der Sie beobachten können, wie der Dienst Nachrichten aus der Warteschlange empfängt.
Hinweis
Die Einrichtungsverfahren und Build-Anweisungen für dieses Beispiel befinden sich am Ende dieses Themas.
In einer Warteschlangenkommunikation kommuniziert der Client über eine Warteschlange mit dem Dienst. Genauer gesagt sendet der Client Nachrichten an eine Warteschlange. Der Dienst empfängt Nachrichten aus der Warteschlange. Der Dienst und der Client müssen daher nicht gleichzeitig ausgeführt werden, um mit einer Warteschlange zu kommunizieren.
Manchmal sendet ein Client eine Reihe von Nachrichten, die in einer Gruppe miteinander verknüpft sind. Wenn Nachrichten zusammen oder in einer bestimmten Reihenfolge verarbeitet werden müssen, kann eine Warteschlange verwendet werden, um sie zu gruppieren, um sie von einer einzigen empfangenden Anwendung zu verarbeiten. Dies ist besonders wichtig, wenn mehrere empfangende Anwendungen auf einer Gruppe von Servern vorhanden sind, und es ist erforderlich, sicherzustellen, dass eine Gruppe von Nachrichten von derselben empfangenden Anwendung verarbeitet wird. In die Warteschlange eingereihte Sitzungen sind ein Mechanismus zum Senden und Empfangen eines zugehörigen Satzes von Nachrichten, die alle gleichzeitig verarbeitet werden müssen. Damit Warteschlangensitzungen dieses Muster bieten, ist eine Transaktion erforderlich.
Im Beispiel sendet der Client eine Reihe von Nachrichten als Teil einer Sitzung im Rahmen einer einzelnen Transaktion an den Dienst.
Der Dienstvertrag ist IOrderTaker, der einen unidirektionalen Dienst definiert, der für die Verwendung mit Warteschlangen geeignet ist. Der in dem Vertrag im folgenden Beispielcode verwendete SessionMode zeigt an, dass die Nachrichten zu der Sitzung gehören.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface IOrderTaker
{
[OperationContract(IsOneWay = true)]
void OpenPurchaseOrder(string customerId);
[OperationContract(IsOneWay = true)]
void AddProductLineItem(string productId, int quantity);
[OperationContract(IsOneWay = true)]
void EndPurchaseOrder();
}
Der Dienst definiert Dienstvorgänge so, dass der erste Vorgang an einer Transaktion beteiligt ist, die Transaktion aber nicht automatisch abgeschlossen wird. Nachfolgende Vorgänge werden auch in derselben Transaktion aufgeführt, aber nicht automatisch abgeschlossen. Der letzte Vorgang in der Sitzung schließt die Transaktion automatisch ab. Daher wird dieselbe Transaktion für mehrere Vorgangsaufrufe im Servicevertrag verwendet. Wenn eine der Vorgänge eine Ausnahme auslöst, wird die Transaktion zurückgesetzt, und die Sitzung wird wieder in die Warteschlange eingefügt. Nach erfolgreichem Abschluss des letzten Vorgangs wird die Transaktion festgeschrieben. Der Dienst verwendet PerSession als InstanceContextMode, um alle Nachrichten in einer Sitzung in derselben Instanz des Dienstes zu empfangen.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class OrderTakerService : IOrderTaker
{
PurchaseOrder po;
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = false)]
public void OpenPurchaseOrder(string customerId)
{
Console.WriteLine("Creating purchase order");
po = new PurchaseOrder(customerId);
}
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = false)]
public void AddProductLineItem(string productId, int quantity)
{
po.AddProductLineItem(productId, quantity);
Console.WriteLine("Product " + productId + " quantity " +
quantity + " added to purchase order");
}
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public void EndPurchaseOrder()
{
Console.WriteLine("Purchase Order Completed");
Console.WriteLine();
Console.WriteLine(po.ToString());
}
}
Der Dienst wird selbst gehostet. Bei Verwendung des MSMQ-Transports muss die verwendete Warteschlange im Voraus erstellt werden. Dies kann manuell oder über Code erfolgen. In diesem Beispiel enthält der Dienst System.Messaging Code, der das Vorhandensein der Warteschlange überprüft und sie bei Bedarf erstellt. Der Warteschlangenname wird mithilfe der AppSettings Klasse aus der Konfigurationsdatei gelesen.
// Host the service within this EXE console application.
public static void Main()
{
// Get MSMQ queue name from app settings 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 OrderTakerService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderTakerService)))
{
// 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();
// Close the ServiceHost to shutdown the service.
serviceHost.Close();
}
}
Der MSMQ-Warteschlangenname wird in einem AppSettings-Abschnitt der Konfigurationsdatei angegeben. Der Endpunkt für den Dienst wird im Abschnitt "system.serviceModel" der Konfigurationsdatei definiert und gibt die netMsmqBinding Bindung an.
<appSettings>
<!-- Use appSetting to configure MSMQ queue name. -->
<add key="queueName" value=".\private$\ServiceModelSamplesSession" />
</appSettings>
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.OrderTakerService"
behaviorConfiguration="CalculatorServiceBehavior">
...
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesSession"
binding="netMsmqBinding"
contract="Microsoft.ServiceModel.Samples.IOrderTaker" />
...
</service>
</services>
...
</system.serviceModel>
Der Client erstellt einen Transaktionsbereich. Alle Nachrichten in der Sitzung werden innerhalb des Transaktionsbereichs an die Warteschlange gesendet, was dazu führt, dass sie als Atomeinheit behandelt wird, bei der alle Nachrichten erfolgreich sind oder fehlschlagen. Die Transaktion wird durch das Aufrufen von Complete zugesichert.
//Create a transaction scope.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
// Create a client with given client endpoint configuration.
OrderTakerClient client = new OrderTakerClient("OrderTakerEndpoint");
// Open a purchase order.
client.OpenPurchaseOrder("somecustomer.com");
Console.WriteLine("Purchase Order created");
// Add product line items.
Console.WriteLine("Adding 10 quantities of blue widget");
client.AddProductLineItem("Blue Widget", 10);
Console.WriteLine("Adding 23 quantities of red widget");
client.AddProductLineItem("Red Widget", 23);
// Close the purchase order.
Console.WriteLine("Closing the purchase order");
client.EndPurchaseOrder();
//Closing the client gracefully closes the connection and cleans up resources.
client.Close();
// Complete the transaction.
scope.Complete();
}
Hinweis
Sie können nur eine Transaktion für alle Nachrichten in der Sitzung verwenden, und alle Nachrichten in der Sitzung müssen gesendet werden, bevor die Transaktion abgeschlossen wird. Durch das Schließen des Clients wird die Sitzung geschlossen. Daher muss der Client geschlossen werden, bevor die Transaktion abgeschlossen ist, um alle Nachrichten in der Sitzung an die Warteschlange zu senden.
Wenn Sie das Beispiel ausführen, werden die Client- und Dienstaktivitäten sowohl in den Dienst- als auch in den Clientkonsolenfenstern angezeigt. Sie können sehen, dass der Dienst Nachrichten vom Client empfängt. Drücken Sie die EINGABETASTE in den einzelnen Konsolenfenstern, um den Dienst und den Client zu schließen. Da die Warteschlange verwendet wird, müssen der Client und der Dienst nicht gleichzeitig laufen. Sie können den Client ausführen, ihn herunterfahren und dann den Dienst starten und trotzdem seine Nachrichten erhalten.
Auf dem Client.
Purchase Order created
Adding 10 quantities of blue widget
Adding 23 quantities of red widget
Closing the purchase order
Press <ENTER> to terminate client.
Beim Dienst.
The service is ready.
Press <ENTER> to terminate service.
Creating purchase order
Product Blue Widget quantity 10 added to purchase order
Product Red Widget quantity 23 added to purchase order
Purchase Order Completed
Purchase Order: 7c86fef0-2306-4c51-80e6-bcabcc1a6e5e
Customer: somecustomer.com
OrderDetails
Order LineItem: 10 of Blue Widget @unit price: $2985
Order LineItem: 23 of Red Widget @unit price: $156
Total cost of this order: $33438
Order status: Pending
Einrichten, Erstellen und Ausführen des Beispiels
Stellen Sie sicher, dass Sie das One-Time Setup-Verfahren für die Windows Communication Foundation-Beispieleausgeführt haben.
Um die C#-, C++- oder Visual Basic .NET-Edition der Lösung zu erstellen, befolgen Sie die Anweisungen im Erstellen der Windows Communication Foundation-Beispiele.
Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.
Standardmäßig wird mit NetMsmqBinding die Transportsicherheit aktiviert. Es gibt zwei relevante Eigenschaften für die MSMQ-Transportsicherheit, nämlich MsmqAuthenticationMode und MsmqProtectionLevel.. Standardmäßig ist der Authentifizierungsmodus auf Windows festgelegt und die Schutzebene auf Sign. Damit MSMQ die Authentifizierungs- und Signaturfunktion bereitstellt, muss sie Teil einer Domäne sein und die Active Directory-Integrationsoption für MSMQ muss installiert werden. Wenn Sie dieses Beispiel auf einem Computer ausführen, der diese Kriterien nicht erfüllt, wird eine Fehlermeldung angezeigt.
Ausführen des Beispiels auf einem Computer, der einer Arbeitsgruppe beigetreten ist
Wenn Ihr Computer nicht Teil einer Domäne ist oder keine Active Directory-Integration installiert ist, deaktivieren Sie die Transportsicherheit, indem Sie den Authentifizierungsmodus und die Schutzstufe wie
Nonein der folgenden Beispielkonfiguration gezeigt festlegen.<system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.OrderTakerService" behaviorConfiguration="OrderTakerServiceBehavior"> <host> <baseAddresses> <add baseAddress= "http://localhost:8000/ServiceModelSamples/service"/> </baseAddresses> </host> <!-- Define NetMsmqEndpoint --> <endpoint address= "net.msmq://localhost/private/ServiceModelSamplesSession" binding="netMsmqBinding" bindingConfiguration="Binding1" contract="Microsoft.ServiceModel.Samples.IOrderTaker" /> <!-- The mex endpoint is exposed at--> <!--http://localhost:8000/ServiceModelSamples/service/mex. --> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <bindings> <netMsmqBinding> <binding name="Binding1"> <security mode="None" /> </binding> </netMsmqBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="OrderTakerServiceBehavior"> <serviceMetadata httpGetEnabled="True"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>Stellen Sie sicher, dass Sie die Konfiguration auf dem Server und dem Client ändern, bevor Sie das Beispiel ausführen.
Hinweis
Das Festlegen des Sicherheitsmodus auf
Noneentspricht der Einstellung von MsmqAuthenticationMode, MsmqProtectionLevel undMessageSicherheit aufNone.