Esempio di conversazioni

Questo esempio mostra come un servizio del flusso di lavoro possa effettuare conversazioni parallele con più client sullo stesso contratto. L'esempio illustra come correlare messaggi inviati per lo stesso contratto e la stessa operazione ma che devono essere gestiti in modo diverso perché inviati da client diversi. Per realizzare conversazioni parallele questo esempio utilizza la funzionalità "contesto conversazione" fornita dai servizi del flusso di lavoro.

Nota

Per poter essere generato ed eseguito, l'esempio richiede che sia installato .NET Framework versione 3.5. Per aprire il progetto e i file della soluzione è necessario Visual Studio 2008.

Per ulteriori informazioni che configura questo esempio, vedere One-time Setup Procedure for Windows Communication Foundation Samples.

Questo esempio utilizza anche comunicazione duplex asincrona così che il servizio del flusso di lavoro e il client possono comunicare in modo asincrono. Nella comunicazione di tipo duplex, le due applicazioni devono scambiare un contesto prima che la comunicazione possa iniziare. Il servizio che inizia la conversazione riceve il contesto nella risposta al messaggio. I servizi del flusso di lavoro forniscono questa funzionalità. Per supportare la comunicazione dal servizio ricevente al servizio mittente, quest'ultimo deve inviare le informazioni relative al contesto nel primo messaggio. L'architettura dell'esempio è illustrata nella figura seguente.

Architettura dell'esempio di conversazioni

Esempio di conversazioni

Nell'esempio viene illustrato il seguente scenario.

Un cliente invia un ordine. In risposta a ciò, il fornitore vuole ottenere un preventivo da tre diversi fornitori di servizi logistici per consegnare l'ordine. Il fornitore invia un messaggio a tutti e tre i fornitori. Ognuno di essi invia un preventivo facendo riferimento alla stessa operazione sullo stesso contratto. Poiché il flusso di lavoro del fornitore utilizza il contesto conversazione, la funzionalità può correlare i preventivi alla corretta attività di ricezione per elaborarli ulteriormente. Il fornitore riceve tutti i preventivi, sceglie il più basso e l'invia al cliente.

In questo esempio comunicano cinque entità:

  • Servizio clienti
    Il servizio clienti invia l'ordine al fornitore, insieme a un contesto che il servizio del fornitore utilizza in un secondo momento per comunicare nuovamente con il servizio clienti. Questo flusso di lavoro di base contiene un'attività Send iniziale che invia il messaggio di richiesta dell'ordine di acquisto con l'ordine di acquisto e il contesto come payload. Un'attività Receive aspetta una risposta dal servizio del fornitore.
    Il contesto che il servizio clienti invia è associato all'attività Receive. Il gestore "prima dell'invio" dell'attività Send contiene codice che ottiene il contesto dall'attività Receive. L'attività Receive include il metodo GetContext seguente che viene chiamato per ottenere il contesto.

    private void PrepareOrder(object sender, SendActivityEventArgs e)
    {
        this.order.Amount = 1000;
        this.order.OrderId = 1234;
        this.contextToSend = this.ReceiveOrderDetails.Context;
    }
    
  • Servizio del fornitore
    Il servizio del fornitore comunica con tre provider di servizi logistici. A questo scopo, utilizza una combinazione di un token contesto univoco per ogni conversazione e comunicazione duplex asincrona. Invia il contesto nel corpo del messaggio della comunicazione tra i servizi di cliente e fornitore.
    Prima di comunicare con i provider logistici, il servizio del fornitore riceve il messaggio dal servizio clienti. In questo messaggio, il servizio del fornitore riceve anche il contesto che utilizza per comunicare nuovamente con il servizio clienti. Il servizio flusso di lavoro del fornitore applica questo contesto all'attività Send utilizzata per inviare un messaggio al servizio client. Il codice che implementa questa funzionalità è nel gestore di codice dell'attività Code nella prima attività Receive, come mostra il codice seguente.

    private void AcceptOrder(object sender, EventArgs e)
    {
        Console.WriteLine("Order Received...");
        this.supplierAck = "Order Received on " + DateTime.Now;
        this.SendOrderDetails.Context = this.customerContext;
    }
    

    Quando il servizio del fornitore riceve un messaggio dal cliente, il fornitore inizia tre conversazioni parallele con i tre provider logistici. Ogni ramo della conversazione ha un'attività Send e un'attività Receive, come mostra l'illustrazione precedente. Le attività Send di ogni ramo inviano il messaggio a un fornitore di servizi logistici. L'attività Receive corrispondente di quel ramo deve recuperare il messaggio dal fornitore. A tale scopo, l'attività Send nel payload del messaggio deve inviare un contesto univoco nel payload stesso. Il provider logistico utilizza quindi questo contesto nell'intestazione del messaggio quando restituisce il messaggio con il preventivo.
    Per impostazione predefinita, ogni attività Receive ha un contesto radice. Per rendere univoca l'attività Receive, l'attività Receive definisce un contesto il cui ambito è relativo a un'attività padre diversa dall'attività radice. Nell'esempio seguente, la proprietà del token contesto di ogni attività Receive nella conversazione parallela ha un nome univoco e ha come ambito l'attività parallela nella quale è contenuta. Quando l'attività Send all'interno di ognuno dei rami paralleli ottiene un contesto dall'attività Receive, ottiene un contesto univoco per quell'attività Receive. Questo contesto univoco viene anche utilizzato per creare un nome per la coda sulla quale l'attività Receive è in ascolto. Quando il provider logistico invia il preventivo con il contesto nell'intestazione, il livello di invio del servizio del flusso di lavoro l'utilizza per creare un nome della coda appropriato e mettere in coda il messaggio cui in seguito fa riferimento l'attività Receive.
    private void PrepareShipper2Request(object sender, SendActivityEventArgs e)
    {
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine("RequestShippingQuote from Shipper2");
    Console.ResetColor();
    this.contextShipper2 = this.ReceiveQuoteFromShipper2.Context;
    }
    I flussi di lavoro del provider logistico ricevono la richiesta di preventivo dal fornitore, insieme al contesto. Il contesto viene applicato all'attività Send che restituisce il messaggio al fornitore, come mostra il codice seguente.

    private void AcceptQuoteRequest(object sender, EventArgs e)
    {
        Console.ForegroundColor = ConsoleColor.White;
        Console.WriteLine("Received ShippingQuote Request");
        this.supplierAck = "Working on quote...";
        Console.ResetColor();
        this.SendShippingQuote.Context(this.supplierContext);
    }
    

Per impostare, compilare ed eseguire l'esempio DIBLOOK

  1. Per impostazione predefinita, questo esempio non utilizza persistenza. Se si desidera la persistenza, sarà necessario aggiungere la voce <WorkflowRuntime> nel file App.config per ognuna delle soluzioni. La voce deve essere sotto la sezione behaviors, come mostrato nell'esempio seguente.

    <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehavior"  >
              <serviceMetadata httpGetEnabled="false" />
              <serviceDebug includeExceptionDetailInFaults="true" />
              <workflowRuntime name="WorkflowServiceHostRuntime" validateOnCreate="true" enablePerformanceCounters="true">
                <services>
                  <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                       connectionString="Data Source=localhost\sqlexpress;Initial Catalog=ServiceModelSamples_ServiceWorkflowStore;Integrated Security=True;Pooling=False"
                       LoadIntervalSeconds="1" UnLoadOnIdle= "true" />
                </services>
              </workflowRuntime>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
  2. Oltre alla voce <WorkflowRuntime> nella sezione behaviors, viene aggiunto anche un servizio di persistenza SQL. Eseguire lo script CreateStores.cmd situato nell'argomento One-Time Setup Procedure for the Windows Communication Foundation Samples. Lo script CreateStores.cmd crea il database ServiceModelSamples_ServiceWorkflowStore. Per impostazione predefinita, questi database sono creati in un database SQL Server 2005 Express Edition Server 2005 Express Edition. Verificare che si abbia SQL Server Express installato nel computer. Se non si vuole installare SQL Server Express e si preferisce utilizzare SQL Server, assicurarsi di modificare le stringhe di connessione nei file App.config per i database della persistenza.

  3. Quando tutti i servizi del flusso di lavoro sono in esecuzione, premere INVIO nel flusso di lavoro client per visualizzare tutti i flussi di lavoro che comunicano l'uno con l'altro. L'ordine di acquisto viene inviato al fornitore che, a sua volta, invia richieste di preventivi logistici a tutti i fornitori di servizi logistici. Quando il fornitore riceve i preventivi, è possibile vedere che viene inviato al cliente il preventivo più basso. È anche possibile verificare i token del contesto per ogni caso. Ciò aiuta a comprendere i contesti univoci inviati a ogni provider logistico.

Invia commenti su questo argomento a Microsoft.