Benutzerdefinierter DemuxCustom Demux

In diesem Beispiel wird veranschaulicht, wie MSMQ-Nachrichtenheader unterschiedlichen Dienstvorgängen zugeordnet werden können, damit Windows Communication Foundation (WCF), bei denen services MsmqIntegrationBinding besteht keine Einschränkung auf die Verwendung eines einzigen Dienstvorgangs aus, wie in der Message Queuing zu Windows Communication Foundation und Windows Communication Foundation zu Message Queuing Beispiele.This sample demonstrates how MSMQ message headers can be mapped to different service operations so that Windows Communication Foundation (WCF) services that use MsmqIntegrationBinding are not limited to using one service operation as demonstrated in the Message Queuing to Windows Communication Foundation and Windows Communication Foundation to Message Queuing samples.

Der Dienst ist in diesem Beispiel eine selbst gehostete Konsolenanwendung, sodass Sie den Dienst beobachten können, der Nachrichten in Warteschlangen empfängt.The service in this sample is a self-hosted console application to enable you to observe the service that receives queued messages.

Der Dienstvertrag ist IOrderProcessor und definiert einen unidirektionalen Dienst, der für die Verwendung mit Warteschlangen geeignet ist.The service contract is IOrderProcessor, and defines a one-way service that is suitable for use with queues.

[ServiceContract]  
[KnownType(typeof(PurchaseOrder))]  
[KnownType(typeof(String))]  
public interface IOrderProcessor  
{  
    [OperationContract(IsOneWay = true, Name = "SubmitPurchaseOrder")]  
    void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);  

    [OperationContract(IsOneWay = true, Name = "CancelPurchaseOrder")]  
    void CancelPurchaseOrder(MsmqMessage<string> ponumber);  
}  

Eine MSMQ-Nachricht besitzt keinen Aktionsheader.An MSMQ message does not have an Action header. Es ist nicht möglich, Vorgangsverträgen unterschiedliche MSMQ-Nachrichten automatisch zuzuordnen.It is not possible to map different MSMQ messages to operation contracts automatically. Deshalb kann es nur einen Vorgangsvertrag geben.Therefore, there can be only one operation contract. Um diese Einschränkung zu umgehen, implementiert der Dienst die SelectOperation-Methode der IDispatchOperationSelector-Schnittstelle.To overcome this limitation, the service implements the SelectOperation method of the IDispatchOperationSelector interface. Die SelectOperation-Methode ermöglicht dem Dienst, einem bestimmten Dienstvorgang einen bestimmten Nachrichtenheader zuzuordnen.The SelectOperation method enables the service to map a given header of the message to a particular service operation. In diesem Beispiel wird den Dienstvorgängen der Bezeichnungsheader der Nachricht zugeordnet.In this sample, the message's label header is mapped to the service operations. Der Name-Parameter des Vorgangsvertrags legt fest, welcher Dienstvorgang für eine bestimmte Nachrichtenbezeichnung weitergeleitet werden muss.The Name parameter of the operation contract determines which service operation must be dispatched for a given message label. Wenn der Bezeichnungsheader der Nachricht z. B. "SubmitPurchaseOrder" enthält, wird der "SubmitPurchaseOrder"-Dienstvorgang aufgerufen.For example, if the message's label header contains "SubmitPurchaseOrder", the "SubmitPurchaseOrder" service operation is invoked.

public class OperationSelector : IDispatchOperationSelector  
{  
    public string SelectOperation(ref System.ServiceModel.Channels.Message message)  
    {  
        MsmqIntegrationMessageProperty property = MsmqIntegrationMessageProperty.Get(message);  
        return property.Label;  
    }  
}  

Der Dienst muss die ApplyDispatchBehavior(ContractDescription, ServiceEndpoint, DispatchRuntime)-Methode der IContractBehavior-Schnittstelle implementieren, wie im folgenden Beispielcode dargestellt.The service must implement the ApplyDispatchBehavior(ContractDescription, ServiceEndpoint, DispatchRuntime) method of the IContractBehavior interface as shown in the following sample code. Diese wendet den benutzerdefinierten OperationSelector auf die Dienstframework-Dispatchlaufzeit an.This applies the custom OperationSelector to the service framework dispatch runtime.

void IContractBehavior.ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime dispatch)  
{  
    dispatch.OperationSelector = new OperationSelector();  
}  

Eine Nachricht muss den ContractFilter des Verteilers durchlaufen, bevor die Vorgangsauswahl erreicht wird.A message must pass through the dispatcher's ContractFilter before getting to the OperationSelector. Standardmäßig wird eine Nachricht zurückgewiesen, wenn ihre Aktion auf keinem der vom Dienst implementierten Verträge gefunden werden kann.By default a message is rejected if its action cannot be found on any contract implemented by the service. Um diese Prüfung zu vermeiden, implementieren wir ein IEndpointBehavior namens MatchAllFilterBehavior, das es allen Nachrichten ermöglicht, den ContractFilter zu passieren, indem der MatchAllMessageFilter folgendermaßen angewendet wird.To avoid this check, we implement an IEndpointBehavior named MatchAllFilterBehavior, which allows any message to pass through the ContractFilter by applying the MatchAllMessageFilter as follows.

public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)  
{  
    endpointDispatcher.ContractFilter = new MatchAllMessageFilter();  
}  

Wenn der Dienst eine Nachricht empfängt, wird der entsprechende Dienstvorgang mithilfe der Informationen im Bezeichnungsheader verteilt.When a message is received by the service, the appropriate service operation is dispatched using the information provided by the label header. Der Nachrichtentext wird in ein PurchaseOrder-Objekt deserialisiert, wie im folgenden Beispielcode dargestellt.The body of the message is deserialized into a PurchaseOrder object, as shown in the following sample code.

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]  
public void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg)  
{  
    PurchaseOrder po = (PurchaseOrder)msg.Body;  
    Random statusIndexer = new Random();  
    po.Status = (OrderStates)statusIndexer.Next(3);  
    Console.WriteLine("Processing {0} ", po);  
}  

Der Dienst ist selbst gehostet.The service is self-hosted. Bei der Verwendung von MSMQ muss die Warteschlange im Voraus erstellt werden.When using the MSMQ, the queue that is used must be created in advance. Dies kann manuell erfolgen oder mithilfe eines Codes.This can be done manually or through code. In diesem Beispiel enthält der Dienst einen Code, um zu überprüfen, ob die Warteschlange bereits vorhanden ist und um die Warteschlange gegebenenfalls zu erstellen.In this sample, the service contains code to check for the existence of the queue and creates it if the queue does not exist. Der Warteschlangenname wird aus der Konfigurationsdatei gelesen.The queue name is read from the configuration file.

public static void Main()  
{  
    // Get MSMQ queue name from app 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 CalculatorService type.  
    using (ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService)))  
    {                 
        ServiceEndpoint endpoint = serviceHost.Description.Endpoints[0];  
        endpoint.Behaviors.Add(new MatchAllFilterBehavior());  

        //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.ReadLine();  

        // Close the ServiceHost to shutdown the service.  
        serviceHost.Close();  
    }  
}  

Der MSMQ-Warteschlangenname wird im appSettings-Abschnitt der Konfigurationsdatei angegeben.The MSMQ queue name is specified in an appSettings section of the configuration file.

Hinweis

Im Warteschlangennamen wird ein Punkt (.) für den lokalen Computer verwendet, und in der Pfadangabe werden umgekehrte Schrägstriche als Trennzeichen verwendet.The queue name uses a dot (.) for the local computer and backslash separators in its path. Die WCF-Endpunktadresse gibt ein msmq.formatname-Schema und verwendet "localhost" für den lokalen Computer.The WCF endpoint address specifies a msmq.formatname scheme, and uses localhost for the local computer. Dem Schema folgt eine ordnungsgemäß entsprechend den Namens- und Adressierungsrichtlinien des MSMQ-Formats formatierte Warteschlangenadresse.What follows the scheme is a properly formatted queue address according to the MSMQ Format name addressing guidelines.

<appSettings>  
    <!-- Use appSetting to configure the MSMQ queue name. -->  
    <add key="queueName" value=".\private$\Orders" />  
</appSettings>  

Hinweis

Dieses Beispiel erfordert die Installation von Message Queuing.This sample requires the installation of Message Queuing.

Starten Sie den Dienst, und führen Sie den Client aus.Start the service and run the client.

Auf dem Client wird die folgende Ausgabe angezeigt.The following output is seen on the client.

Placed the order:Purchase Order: 28fc457a-1a56-4fe0-9dde-156965c21ed6  
        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  
Canceled the Order: 28fc457a-1a56-4fe0-9dde-156965c21ed6  
Press <ENTER> to terminate client.  

Auf dem Dienst muss die folgende Ausgabe angezeigt werden.The following output must be seen on the service.

The service is ready.  
Press <ENTER> to terminate service.  
Processing Purchase Order: 28fc457a-1a56-4fe0-9dde-156965c21ed6  
        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: Shipped  
Purchase Order 28fc457a-1a56-4fe0-9dde-156965c21ed6 is canceled  

So können Sie das Beispiel einrichten, erstellen und ausführenTo set up, build, and run the sample

  1. Stellen Sie sicher, dass Sie ausgeführt haben die Setupprozedur für die Windows Communication Foundation-Beispiele zum einmaligen.Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. Wenn der Dienst zuerst ausgeführt wird, wird überprüft, ob die Warteschlange vorhanden ist.If the service is run first, it will check to ensure that the queue is present. Ist die Warteschlange nicht vorhanden, wird sie vom Dienst erstellt.If the queue is not present, the service will create one. Sie können zuerst den Dienst ausführen, um die Warteschlange zu erstellen, oder Sie können sie über den MSMQ-Warteschlangen-Manager erstellen.You can run the service first to create the queue, or you can create one via the MSMQ Queue Manager. Führen Sie zum Erstellen einer Warteschlange in Windows 2008 die folgenden Schritte aus:Follow these steps to create a queue in Windows 2008.

    1. Öffnen Sie Server-Manager in Visual Studio 2012Visual Studio 2012.Open Server Manager in Visual Studio 2012Visual Studio 2012.

    2. Erweitern Sie die Funktionen Registerkarte.Expand the Features tab.

    3. Mit der rechten Maustaste Private Meldungswarteschlangen, und wählen Sie neu, Private Warteschlange.Right-click Private Message Queues, and select New, Private Queue.

    4. Überprüfen Sie die transaktional Feld.Check the Transactional box.

    5. Geben Sie ServiceModelSamplesTransacted als Namen für die neue Warteschlange.Enter ServiceModelSamplesTransacted as the name of the new queue.

  3. Um die C#- oder Visual Basic .NET-Edition der Projektmappe zu erstellen, befolgen Sie die unter Building the Windows Communication Foundation Samplesaufgeführten Anweisungen.To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  4. Um das Beispiel in einer Einzelcomputer- oder computerübergreifenden Konfiguration ausführen möchten, folgen Sie den Anweisungen Ausführen der Windows Communication Foundation-Beispiele.To run the sample in a single- or cross- computer configuration, follow the instructions in Running the Windows Communication Foundation Samples.

So führen Sie das Beispiel computerübergreifend ausTo run the sample across computers

  1. Kopieren Sie die Dienstprogrammdateien aus dem Ordner \service\bin\ (unterhalb des sprachspezifischen Ordners) auf den Dienstcomputer.Copy the service program files from the \service\bin\ folder, under the language-specific folder, to the service computer.

  2. Kopieren Sie die Clientprogrammdateien aus dem Ordner \client\bin\ (unterhalb des sprachspezifischen Ordners) auf den Clientcomputer.Copy the client program files from the \client\bin\ folder, under the language-specific folder, to the client computer.

  3. Ändern Sie in der Datei Client.exe.config den Wert von orderQueueName, und geben Sie anstelle von "." den Namen des Dienstcomputers an.In the Client.exe.config file, change the orderQueueName to specify the service computer name instead of ".".

  4. Starten Sie auf dem Dienstcomputer Service.exe an einer Eingabeaufforderung.On the service computer, launch Service.exe from a command prompt.

  5. Starten Sie auf dem Clientcomputer Client.exe an einer Eingabeaufforderung.On the client computer, launch Client.exe from a command prompt.

Wichtig

Die Beispiele sind möglicherweise bereits auf dem Computer installiert.The samples may already be installed on your computer. Suchen Sie nach dem folgenden Verzeichnis (Standardverzeichnis), bevor Sie fortfahren.Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Wenn dieses Verzeichnis nicht vorhanden ist, fahren Sie mit Windows Communication Foundation (WCF) und Windows Workflow Foundation (WF) Samples for .NET Framework 4 aller Windows Communication Foundation (WCF) herunterladen und WFWF Beispiele.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF) and WFWF samples. Dieses Beispiel befindet sich im folgenden Verzeichnis.This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Basic\Binding\MSMQIntegration\CustomDemux

Siehe auchSee Also

Queuing in WCFQueuing in WCF
Message QueuingMessage Queuing