Condividi tramite


Two-Way comunicazione

L'esempio diTwo-Way illustra come eseguire comunicazioni transazioni in coda bidirezionale tramite MSMQ. In questo esempio viene utilizzata l'associazione netMsmqBinding . In questo caso, il servizio è un'applicazione console autonomamente ospitata che consente di monitorare il servizio che riceve messaggi in coda.

Annotazioni

La procedura di installazione e le istruzioni di compilazione per questo esempio si trovano alla fine di questo argomento.

Questo esempio si basa sull'associazione MSMQ transazionata.

Nella comunicazione in coda, il client comunica con il servizio usando una coda. Il client invia messaggi a una coda e il servizio riceve messaggi dalla coda. Non è quindi necessario che il servizio e il client siano in esecuzione contemporaneamente per comunicare tramite una coda.

Questo esempio illustra la comunicazione bidirezionale usando le code. Il cliente invia ordini di acquisto nella coda dall'ambito di una transazione. Il servizio riceve gli ordini, elabora gli ordini e quindi richiama il cliente con lo stato degli ordini derivato dalla coda all'interno dell'ambito di una transazione. Per facilitare la comunicazione bidirezionale, il client e il servizio usano entrambi le code per mettere in coda gli ordini di acquisto e lo stato dell'ordine.

Il contratto di servizio IOrderProcessor definisce operazioni di servizio unidirezionali che sono adatte all'uso dell'accodamento. L'operazione del servizio include l'endpoint di risposta a cui inviare gli stati dell'ordine. L'endpoint di risposta è l'URI della coda per restituire lo stato dell'ordine al client. L'applicazione di elaborazione degli ordini implementa questo contratto.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true)]
    void SubmitPurchaseOrder(PurchaseOrder po, string
                                  reportOrderStatusTo);
}

Il contratto di risposta per l'invio dello stato dell'ordine viene specificato dal client. Il cliente esegue il contratto relativo allo stato dell'ordine. Il servizio usa il proxy generato di questo contratto per inviare di nuovo lo stato dell'ordine al client.

[ServiceContract]
public interface IOrderStatus
{
    [OperationContract(IsOneWay = true)]
    void OrderStatus(string poNumber, string status);
}

Il servizio processa l'ordine di acquisto inviato. OperationBehaviorAttribute viene applicato all'operazione del servizio per specificare l'iscrizione automatica in una transazione utilizzata per ricevere il messaggio dalla coda e il completamento automatico delle transazioni al termine dell'operazione del servizio. La Orders classe incapsula la funzionalità di elaborazione degli ordini. In questo caso, aggiunge l'ordine di acquisto a un dizionario. La transazione in cui è inclusa l'operazione del servizio è disponibile per le operazioni nella Orders classe .

L'operazione del servizio, oltre a elaborare l'ordine di acquisto inviato, risponde al cliente sullo stato dell'ordine.

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SubmitPurchaseOrder(PurchaseOrder po, string reportOrderStatusTo)
{
    Orders.Add(po);
    Console.WriteLine("Processing {0} ", po);
    Console.WriteLine("Sending back order status information");
    NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding("ClientCallbackBinding");
    OrderStatusClient client = new OrderStatusClient(msmqCallbackBinding, new EndpointAddress(reportOrderStatusTo));

    // Please note that the same transaction that is used to dequeue the purchase order is used
    // to send back order status.
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
    {
        client.OrderStatus(po.PONumber, po.Status);
        scope.Complete();
    }
    //Close the client.
    client.Close();
}

Il nome della coda MSMQ viene specificato in una sezione appSettings del file di configurazione. L'endpoint per il servizio viene definito nella sezione System.ServiceModel del file di configurazione.

Annotazioni

Il nome della coda MSMQ e l'indirizzo dell'endpoint usano convenzioni di indirizzamento leggermente diverse. Il nome della coda MSMQ utilizza un punto (.) per il computer locale e i separatori di backslash nel suo percorso. L'indirizzo endpoint di Windows Communication Foundation (WCF) specifica uno schema net.msmq, usa "localhost" per il computer locale e usa barre oblique nel percorso. Per leggere da una coda ospitata su una macchina remota, sostituire "." e "localhost" con il nome della macchina remota.

Il servizio è autogestito. Quando si usa il trasporto MSMQ, la coda usata deve essere creata in anticipo. Questa operazione può essere eseguita manualmente o tramite il codice. In questo esempio il servizio verifica l'esistenza della coda e lo crea, se necessario. Il nome della coda viene letto dal file di configurazione. L'indirizzo di base viene usato dallo strumento utilità metadati ServiceModel (Svcutil.exe) per generare il proxy al servizio.

// Host the service within this EXE console application.
public static void Main()
{
    // Get MSMQ queue name from appSettings 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 OrderProcessorService type.
    using (ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService)))
    {
        // 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();
    }
}

Il client crea una transazione. La comunicazione con la coda avviene all'interno dell'ambito della transazione, facendola trattare come un'unità atomica in cui tutti i messaggi hanno successo o falliscono.

// Create a ServiceHost for the OrderStatus service type.
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderStatusService)))
{

    // Open the ServiceHostBase to create listeners and start listening for order status messages.
    serviceHost.Open();

    // Create the purchase order.
    ...

    // Create a client with given client endpoint configuration.
    OrderProcessorClient client = new OrderProcessorClient("OrderProcessorEndpoint");

    //Create a transaction scope.
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
    {
        string hostName = Dns.GetHostName();

        // Make a queued call to submit the purchase order.
        client.SubmitPurchaseOrder(po, "net.msmq://" + hostName + "/private/ServiceModelSamplesTwo-way/OrderStatus");

        // Complete the transaction.
        scope.Complete();
    }

    //Close down the client.
    client.Close();

    Console.WriteLine();
    Console.WriteLine("Press <ENTER> to terminate client.");
    Console.ReadLine();

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

Il codice client implementa il IOrderStatus contratto per ricevere lo stato dell'ordine dal servizio. In questo caso, stampa lo stato dell'ordine.

[ServiceBehavior]
public class OrderStatusService : IOrderStatus
{
    [OperationBehavior(TransactionAutoComplete = true,
                        TransactionScopeRequired = true)]
    public void OrderStatus(string poNumber, string status)
    {
        Console.WriteLine("Status of order {0}:{1} ", poNumber ,
                                                           status);
    }
}

La coda di stato dell'ordine Main viene creata nel metodo . La configurazione client include la configurazione del servizio di stato dell'ordine per ospitare il servizio di stato dell'ordine, come illustrato nella configurazione di esempio seguente.

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

<system.serviceModel>

  <services>
    <service
       name="Microsoft.ServiceModel.Samples.OrderStatusService">
      <!-- Define NetMsmqEndpoint -->
      <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderStatus"
                binding="netMsmqBinding"
                contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
    </service>
  </services>

  <client>
    <!-- Define NetMsmqEndpoint -->
    <endpoint name="OrderProcessorEndpoint"
              address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor"
              binding="netMsmqBinding"
              contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
  </client>

</system.serviceModel>

Quando si esegue l'esempio, le attività client e di servizio vengono visualizzate sia nelle finestre del servizio che della console client. È possibile visualizzare il servizio che riceve messaggi dal client. Premere INVIO in ogni finestra della console per spegnere il servizio e il client.

Il servizio visualizza le informazioni sull'ordine di acquisto e indica che sta inviando lo stato dell'ordine nuovamente alla coda dello stato dell'ordine.

The service is ready.
Press <ENTER> to terminate service.

Processing Purchase Order: 124a1f69-3699-4b16-9bcc-43147a8756fc
        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

Sending back order status information

Il client visualizza le informazioni sullo stato dell'ordine inviate dal servizio.

Press <ENTER> to terminate client.
Status of order 124a1f69-3699-4b16-9bcc-43147a8756fc:Pending

Per configurare, compilare ed eseguire l'esempio

  1. Assicurati di aver eseguito la procedura di installazione di One-Time per gli esempi di Windows Communication Foundation.

  2. Per compilare l'edizione C# o Visual Basic .NET della soluzione, seguire le istruzioni in Compilazione degli esempi di Windows Communication Foundation.

  3. Per eseguire l'esempio in una configurazione con computer singolo o incrociato, seguire le istruzioni riportate in Esecuzione degli esempi di Windows Communication Foundation.

    Annotazioni

    Se si usa Svcutil.exe per rigenerare la configurazione per questo esempio, assicurarsi di modificare i nomi degli endpoint nella configurazione client in modo che corrispondano al codice client.

Per impostazione predefinita con il NetMsmqBinding, la sicurezza del trasporto è abilitata. Esistono due proprietà rilevanti per la sicurezza MsmqAuthenticationMode del trasporto MSMQ.MsmqProtectionLevel.Per impostazione predefinita, la modalità di autenticazione è impostata su Windows e il livello di protezione è impostato su Sign. Affinché MSMQ fornisca la funzionalità di autenticazione e firma, deve far parte di un dominio e deve essere installata l'opzione di integrazione di Active Directory per MSMQ. Se si esegue questo esempio in un computer che non soddisfa questi criteri, viene visualizzato un errore.

Per eseguire l'esempio in un computer aggiunto a un gruppo di lavoro o senza integrazione di Active Directory

  1. Se il computer non fa parte di un dominio o non dispone dell'integrazione di Active Directory installata, disattivare la sicurezza del trasporto impostando la modalità di autenticazione e il livello di protezione su None come illustrato nella configurazione di esempio seguente:

    <configuration>
    
      <appSettings>
        <!-- Use appSetting to configure MSMQ queue name. -->
        <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderProcessor" />
      </appSettings>
    
      <system.serviceModel>
        <services>
          <service
              name="Microsoft.ServiceModel.Samples.OrderProcessorService">
            <!-- Define NetMsmqEndpoint -->
            <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor"
                      binding="netMsmqBinding"
                      bindingConfiguration="TransactedBinding"
                      contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
          </service>
        </services>
    
        <bindings>
          <netMsmqBinding>
            <binding name="TransactedBinding" >
             <security mode="None" />
            </binding>
          </netMsmqBinding>
        </bindings>
    
      </system.serviceModel>
    
    </configuration>
    
  2. La disattivazione della sicurezza per una configurazione client genera quanto segue:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <!-- Use appSetting to configure MSMQ queue name. -->
        <add key="queueName" value=".\private$\ServiceModelSamplesTwo-way/OrderStatus" />
      </appSettings>
    
      <system.serviceModel>
    
        <services>
          <service
             name="Microsoft.ServiceModel.Samples.OrderStatusService">
            <!-- Define NetMsmqEndpoint -->
            <endpoint address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderStatus"
                      binding="netMsmqBinding"
                      bindingConfiguration="TransactedBinding" contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
          </service>
        </services>
    
        <client>
          <!-- Define NetMsmqEndpoint -->
          <endpoint name="OrderProcessorEndpoint"
                    address="net.msmq://localhost/private/ServiceModelSamplesTwo-way/OrderProcessor"
                    binding="netMsmqBinding"
                    bindingConfiguration="TransactedBinding"
                    contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
        </client>
    
        <bindings>
          <netMsmqBinding>
            <binding name="TransactedBinding" >
             <security mode="None" />
            </binding>
          </netMsmqBinding>
        </bindings>
    
      </system.serviceModel>
    
    </configuration>
    
  3. Il servizio per questo esempio crea un'associazione in OrderProcessorService. Aggiungere una riga di codice dopo l'istanza dell'associazione per impostare la modalità di sicurezza su None.

    NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();
    msmqCallbackBinding.Security.Mode = NetMsmqSecurityMode.None;
    
  4. Assicurarsi di modificare la configurazione sia nel server che nel client prima di eseguire l'esempio.

    Annotazioni

    L'impostazione di security mode su None equivale all'impostazione della sicurezza di MsmqAuthenticationMode, MsmqProtectionLevel, o Message su None.