Partager via


Tâche 1 : activer la communication entre le client et son hôte

Dans cette tâche, vous activerez la communication entre votre client et son hôte à travers l'utilisation d'un contrat WCF. L'application hôte appellera une opération sur le client conçue pour démarrer le workflow client et l'initialiser avec une valeur de départ.

De plus, au lieu de créer un autre contrat WCF par une nouvelle interface, vous apprendrez dans cette tâche comment créer un contrat WCF par programmation avec la méthode workflow en premier.

Bb924543.note(fr-fr,VS.90).gifRemarque :
Lorsque le concepteur de flux de travail de Visual Studio est utilisé pour créer ou gérer des services de flux de travail, il produit parfois des erreurs de validation parasites. Si vous êtes en mesure de générer correctement le projet, ignorez les erreurs de validation.

Procédures

Pour créer le contrat de communication hôte local

  1. Remarque   Lorsque le concepteur de workflow de Visual Studio est utilisé pour créer ou gérer des services de workflow, il produit parfois des erreurs de validation parasites. Si vous êtes en mesure de générer correctement le projet, ignorez les erreurs de validation.

  2. Ouvrez la solution WorkflowServiceTutorial.

  3. Dans le noeud de projet WorkflowServiceClient, ouvrez le concepteur de workflow pour ce projet.

  4. Faites glisser une activité ReceiveActivity sur le concepteur et placez-la au-dessus de la première activité SendActivity afin que l'activité ReceiveActivity soit exécutée en premier dans le workflow.

    Cette activité implémentera l'opération définie dans le contrat de communication hôte local.

  5. Sélectionnez l'activité ReceiveActivity et, dans le volet Propriétés, sous ServiceOperationInfo, cliquez sur le bouton de sélection pour ouvrir la boîte de dialogue Choisir une opération.

  6. Vous allez définir un nouveau contrat à l'aide du style de création workflow en premier, donc cliquez sur Ajouter un contrat dans l'angle supérieur droit et mettez Contract1 en surbrillance.

  7. Dans la zone de texte Nom du contrat, nommez votre contrat ILocalHostContract.

  8. Mettez en surbrillance la première opération sous ILocalHostContract et renommez-la StartClientWorkflow.

  9. Dans l'onglet Paramètres, cliquez sur le symbole Ajouter et ajoutez un nouveau paramètre appelé initialValue de type Int32 avec une Direction Intérieure et cliquez sur OK.

  10. Sélectionnez l'activité ReceiveActivity et, sous le volet Propriétés, liez initialValue à la variable globale inputValue.

  11. Sous le volet Propriétés, affectez la valeur True à la propriété CanCreateInstance.

    Un nouveau contrat appelé ILocalHostContract est maintenant défini pour vous par programmation, mais vous devez toujours altérer quelques fichiers avant de pouvoir utiliser ce contrat pour interagir avec votre service de workflow.

  12. Ouvrez App.config dans le projet WorkflowServiceClient.

  13. Ajoutez le code de configuration suivant :

          <services>
            <service name="WorkflowServiceClient.ClientWorkflow" behaviorConfiguration="WorkflowServiceClient.ClientWorkflowBehavior">
              <host>
                <baseAddresses>
                  <add baseAddress="https://localhost:8090/ClientWorkflow" />
                </baseAddresses>
              </host>
              <endpoint address=""
                        binding="wsHttpContextBinding"
                        contract="ILocalHostContract" />
              <endpoint address="mex"
                        binding="mexHttpBinding"
                        contract="IMetadataExchange" />
            </service>
          </services>
          <behaviors>
            <serviceBehaviors>
              <behavior name="WorkflowServiceClient.ClientWorkflowBehavior"  >
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceCredentials>
                  <windowsAuthentication
                      allowAnonymousLogons="false"
                      includeWindowsGroups="true" />
                </serviceCredentials>
              </behavior>
            </serviceBehaviors>
          </behaviors>
    

    Vous avez maintenant défini l'adresse de point de terminaison de votre contrat de communication hôte local. Le client que vous avez utilisé dans ce didacticiel implémentera également ce nouveau contrat.

Pour installer la communication hôte locale

  1. Ouvrez Program.cs et ajoutez les instructions using suivantes en haut du fichier :

    using System.ServiceModel;
    using System.ServiceModel.Description;
    

    Si vous avez créé une solution Visual Basic, cliquez avec le bouton droit de la souris sur le nœud de projet WorkflowServiceClient et sélectionnez Propriétés. Sélectionnez l'onglet Références et, sous Espaces de noms importés, cliquez sur les cases à cocher pour System.ServiceModel et System.ServiceModel.Description.

  2. Vous utiliserez maintenant un WorkflowServiceHost pour activer la communication hôte locale et exécuter les appels de l'opération du workflow client avec le service de workflow, vous devez donc modifier la méthode Main afin que l'application hôte de la console puisse communiquer avec le client du service de workflow. Le code suivant montre la manière dont l'implémentation de Main doit changer pour faciliter la communication hôte locale.

    Shared Sub Main()
        ' Create a WorkflowServiceHost object to listen for operation invocations.
        Using ConsoleHost As New WorkflowServiceHost(GetType(ClientWorkflow))
            Dim waitHandle As New AutoResetEvent(False)
    
            ' Add ChannelManagerService to the list of services used 
            ' by the WorkflowRuntime.
            Dim cms As New ChannelManagerService()
            ConsoleHost.Description.Behaviors.Find(Of WorkflowRuntimeBehavior)().WorkflowRuntime.AddService(cms)
            AddHandler ConsoleHost.Description.Behaviors.Find(Of WorkflowRuntimeBehavior)().WorkflowRuntime.WorkflowCompleted, AddressOf OnWorkflowCompleted
            AddHandler ConsoleHost.Description.Behaviors.Find(Of WorkflowRuntimeBehavior)().WorkflowRuntime.WorkflowTerminated, AddressOf OnWorkflowTerminated
            AddHandler ConsoleHost.Closed, AddressOf OnConsoleClosed
    
            ' Call Open to start receiving messages.
            ConsoleHost.Open()
    
            ' After the client workflow is started, block until receiving waitHandle.Set is called
            ' so that the console application does not exit before the client workflow has completed
            ' and ConsoleHost.Close is called.
            waitHandle.WaitOne()
        End Using
    End Sub
    
    Shared Sub OnWorkflowCompleted(ByVal sender As Object, ByVal e As WorkflowCompletedEventArgs)
        Console.WriteLine("The client workflow has completed." + vbLf + "Press <Enter> to exit the client application.")
        Console.ReadLine()
        WaitHandle.Set()
    End Sub
    
    Shared Sub OnWorkflowTerminated(ByVal sender As Object, ByVal e As WorkflowTerminatedEventArgs)
        Console.WriteLine(e.Exception.Message)
        WaitHandle.Set()
    End Sub
    
    ' After the WorkflowServiceHost transitions to the closed state, allow the console 
    ' application to exit by signaling to the AutoResetEvent object that it is okay to unblock 
    ' the main thread.
    Shared Sub OnConsoleClosed(ByVal sender As Object, ByVal e As EventArgs)
        WaitHandle.Set()
    End Sub
    
    static void Main(string[] args)
    {
        // Create a WorkflowServiceHost object to listen for operation invocations.
        using (WorkflowServiceHost ConsoleHost = new WorkflowServiceHost(typeof(ClientWorkflow)))
        {
            AutoResetEvent waitHandle = new AutoResetEvent(false);
    
            // Add ChannelManagerService to the list of services used 
            // by the WorkflowRuntime.
            ChannelManagerService cms = new ChannelManagerService();
            ConsoleHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime.AddService(cms);
    
            ConsoleHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) 
            { 
                Console.WriteLine("The client workflow has completed. \nPress <Enter> to exit the client application."); 
                Console.ReadLine();
                ConsoleHost.Close();
            };
    
            ConsoleHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
            {
                Console.WriteLine(e.Exception.Message);
                waitHandle.Set();
            };
    
            // After the WorkflowServiceHost transitions to the closed state, allow the console 
            // application to exit by signaling to the AutoResetEvent object that it is okay to unblock 
            // the main thread.
            ConsoleHost.Closed += delegate(object sender, EventArgs e)
            {
                waitHandle.Set();
            };
    
            // Call Open to start receiving messages.
            ConsoleHost.Open();
    
            // After the client workflow is started, block until receiving waitHandle.Set is called
            // so that the console application does not exit before the client workflow has completed
            // and ConsoleHost.Close is called.
            waitHandle.WaitOne();
        }
    }
    
  3. Générez et exécutez votre service client.

  4. Utilisez SvcUtil.exe pour générer le code proxy et le code de configuration nécessaires à l'interaction avec les opérations de communication hôte locales.

    Utilisation de Svcutil.exe

    Pour utiliser Svcutil.exe, consultez ServiceModel Metadata Utility Tool.

    Après avoir généré vos codes proxy et vos fichiers de configuration, ajoutez ces fichiers à votre projet WorkflowServiceClient en effectuant les opérations suivantes :

    1. Naviguez jusqu'au volet Explorateur de solutions.
    2. Cliquez avec le bouton droit de la souris sur le nœud du projet WorkflowServiceClient.
    3. Mettez en surbrillance Ajouter et sélectionnez Élément existant.
    4. Naviguez jusqu'au dossier où SvcUtil.exe a généré les fichiers de code proxy et de configuration.
    5. Sélectionnez les fichiers et cliquez sur OK.
  5. Une fois que vous avez généré vos fichiers de code proxy et de configuration, modifiez le code de configuration dans App.config afin que le nouveau point de terminaison client utilisé pour faciliter la communication hôte locale soit reconnu par l'application hôte. Vous pouvez également utiliser les mêmes informations de configuration de liaison que celles actuellement utilisées pour communiquer avec votre service de workflow si vous le souhaitez. L'exemple de code suivant affiche le code à ajouter à votre fichier App.Config.

        <bindings>
        ...
        </bindings>
        <client>
            <endpoint address="https://localhost:8080/ServerWorkflow" binding="wsHttpContextBinding"
                    bindingConfiguration="WSHttpContextBinding_IWorkflow1" contract="IWorkflow1"
                    name="WSHttpContextBinding_IWorkflow1">
                <identity>
                    <userPrincipalName value="someone@example.com" />
                </identity>
            </endpoint>
            <endpoint address="https://localhost:8090/ClientWorkflow" binding="wsHttpContextBinding"
                    bindingConfiguration="WSHttpContextBinding_IWorkflow1"
                    contract="ILocalHostContract" name="WSHttpContextBinding_ILocalHostContract">
                <identity>
                    <userPrincipalName value="someone@example.com" />
                </identity>
            </endpoint>
        </client>
        <services>
        ...
        </services>
        <behaviors>
        ...
        </behaviors>
    
  6. Maintenant que vous avez généré votre code client de proxy pour communiquer entre l'hôte et le client du service de workflow, vous devez ajouter le code pour appeler l'opération LocalHostContractClient.StartClientWorkflow dans votre workflow client. Ouvrez Program.cs (ou Module1.vb si vous avez créé une solution Visual Basic) et ajoutez le code suivant.

    Class Program
    
        Shared WaitHandle As New AutoResetEvent(False)
    
        Shared Sub Main()
            ' Create a WorkflowServiceHost object to listen for operation invocations.
            Using ConsoleHost As New WorkflowServiceHost(GetType(WorkflowServiceClient.ClientWorkflow))
                Dim waitHandle As New AutoResetEvent(False)
    
                ' Create a client that is used by the host application to communicate with the workflow service client.            Dim LCSClient As New WorkflowServiceClient.LocalHostContractClient("WSHttpContextBinding_ILocalHostContract")
    
                ' Add ChannelManagerService to the list of services used 
                ' by the WorkflowRuntime.
                Dim cms As New ChannelManagerService()
                ConsoleHost.Description.Behaviors.Find(Of WorkflowRuntimeBehavior)().WorkflowRuntime.AddService(cms)
                AddHandler ConsoleHost.Description.Behaviors.Find(Of WorkflowRuntimeBehavior)().WorkflowRuntime.WorkflowCompleted, AddressOf OnWorkflowCompleted
                AddHandler ConsoleHost.Description.Behaviors.Find(Of WorkflowRuntimeBehavior)().WorkflowRuntime.WorkflowTerminated, AddressOf OnWorkflowTerminated
                AddHandler ConsoleHost.Closed, AddressOf OnConsoleClosed
    
                ' Call Open to start receiving messages.
                 ConsoleHost.Open()
    
                Console.WriteLine("Client host service is ready.")            Console.WriteLine("Enter a starting value: ")            ' Read in a number from the user and use it as the initial number in the arithmetic operation calls.            LCSClient.StartClientWorkflow(Int32.Parse(Console.ReadLine()))
    
                ' After the client workflow is started, block until receiving waitHandle.Set is called
                ' so that the console application does not exit before the client workflow has completed
                ' and ConsoleHost.Close is called.
                waitHandle.WaitOne()
            End Using
        End Sub
    
        Shared Sub OnWorkflowCompleted(ByVal sender As Object, ByVal e As WorkflowCompletedEventArgs)
            Console.WriteLine("The client workflow has completed." + vbLf + "Press <Enter> to exit the client application.")
            Console.ReadLine()
            WaitHandle.Set()
        End Sub
    
        Shared Sub OnWorkflowTerminated(ByVal sender As Object, ByVal e As WorkflowTerminatedEventArgs)
            Console.WriteLine(e.Exception.Message)
            WaitHandle.Set()
        End Sub
    
        ' After the WorkflowServiceHost transitions to the closed state, allow the console 
        ' application to exit by signaling to the AutoResetEvent object that it is okay to unblock 
        ' the main thread.
        Shared Sub OnConsoleClosed(ByVal sender As Object, ByVal e As EventArgs)
            WaitHandle.Set()
        End Sub
    End Class
    
    static void Main(string[] args)
    {
        // Create a WorkflowServiceHost object to listen for operation invocations.
        using (WorkflowServiceHost ConsoleHost = new WorkflowServiceHost(typeof(ClientWorkflow)))
        {
            AutoResetEvent waitHandle = new AutoResetEvent(false);
    
            // Create a client that is used by the host application to communicate with the workflow service client.        LocalHostContractClient LCSClient = new LocalHostContractClient("WSHttpContextBinding_ILocalHostContract");
    
            // Add ChannelManagerService to the list of services used 
            // by the WorkflowRuntime.
            ChannelManagerService cms = new ChannelManagerService();
            ConsoleHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime.AddService(cms);
    
            ConsoleHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) 
            { 
                Console.WriteLine("The client workflow has completed. \nPress <Enter> to exit the client application."); 
                Console.ReadLine();
                ConsoleHost.Close();
            };
    
            ConsoleHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
            {
                Console.WriteLine(e.Exception.Message);
                waitHandle.Set();
            };
    
            // After the WorkflowServiceHost transitions to the closed state, allow the console 
            // application to exit by signaling to the AutoResetEvent object that it is okay to unblock 
            // the main thread.
            ConsoleHost.Closed += delegate(object sender, EventArgs e)
            {
                waitHandle.Set();
            };
    
            // Call Open to start receiving messages.
            ConsoleHost.Open();
    
            Console.WriteLine("Client host service is ready.");        Console.WriteLine("Enter a starting value: ");        // Read in a number from the user and use it as the initial number in the arithmetic operation calls.        LCSClient.StartClientWorkflow(Int32.Parse(Console.ReadLine()));
    
            // After the client workflow is started, block until receiving waitHandle.Set is called
            // so that the console application does not exit before the client workflow has completed and 
            // ConsoleHost.Close is called.
            waitHandle.WaitOne();
        }
    }
    

    La valeur True est affectée au CanCreateInstance du ReceiveActivity qui implémente cette opération, une nouvelle instance de workflow sera donc créée et le reste du workflow s'exécutera de la même manière que lors des exercices précédents. De plus, la valeur entrée avec l'invite de commandes sera la valeur de départ initiale utilisée lors de l'appel du reste des opérations arithmétiques dans le service de workflow.

  7. Ouvrez Workflow1.cs (ou Workflow1.vb si vous avez créé une solution Visual Basic) et supprimez la ligne de code qui affecte le nombre 1 à la variable inputValue dans l'implémentation de méthode sendActivity2_BeforeSend afin que lorsque l'utilisateur entre une valeur dans l'invite de commandes, celle-ci soit utilisée comme valeur de départ initiale pour tous les appels d'opération dans le service de workflow. L'exemple de code suivant montre à quoi doit ressembler l'implémentation de méthode du gestionnaire d'événements modifiée.

    Private Sub sendActivity2_BeforeSend(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.SendActivityEventArgs)
        Console.WriteLine("The initial input value is {0}", inputValue)
    End Sub
    
    private void sendActivity2_BeforeSend(object sender, SendActivityEventArgs e)
    {
        Console.WriteLine("The initial input value is {0}", inputValue);
    }
    
  8. Générez et exécutez la solution WorkflowServiceTutorial. Vous pouvez observer une sortie semblable à celle-ci dans l'application hôte de la console.

    Client host service is ready.
    Enter a starting value:
    7
    A service instance has successfully been created.
    The initial input value is 7
    The value after invoking the Add operation is 7
    The new input value is 2
    The value after invoking the Subtract operation is 5
    The new input value is 6
    The value after invoking the Multiply operation is 30
    The new input value is 3
    The value after invoking the Divide operation is 10
    The workflow service instance has successfully shutdown.
    The client workflow has completed.
    Press <Enter> to exit the client application.
    

Voir aussi

Référence

Tâche 1 : activer la communication entre le client et son hôte

Copyright © 2007 par Microsoft Corporation. Tous droits réservés.