Workflow Foundation > Tutoriaux > Création d'un workflow séquentiel simple
       Accueil
       L'équipe


       Présentation
       Activités WF
       Articles
       Tutoriaux
       Trucs & Astuces


       Forum (MSDN)
       Téléchargements
       Ressources FR
       Annuaire des liens
       Formation (WW)


       Administration


 


Ne ratez pas le MSDN et TechNet Tour 2008 : votre nouveau rendez-vous Développeur dans votre région

Introduction

Il y a quelques temps, je me suis lancé à la découverte de Windows Workflow Foundation, et pour dire vrai, plus j’avance dans mon exploration, plus je prends du plaisir à utiliser ce Framework.

Pour revenir quelques semaines en arrière, voici un exemple de workflow séquentiel illustré et vraiment très simple. Je vais essayer d’écrire plusieurs documents sur le sujet, en augmentant le niveau de complexité à chaque fois, mais toujours dans une optique de « découverte pas à pas ».

Attention, cet article a initialement été écrit avec la Beta 1.2 de Workflow Foundation. Cependant, les modifications et corrections apportées par la Beta 2 y sont maintenant présentes.

Définitions

Workflow : Un workflow est un ensemble d’actions (étapes) s’enchainant dans un ordre prédéfinit. Ces actions peuvent s’enchainées en fonction de conditions, d’interactions avec des processus informatiques ou en fonction d’interactions humaines.

Activité : Une activité est un composant réutilisable représentant une étape d’un workflow.

Problématique

Pour cet exemple, l’objectif sera de réaliser une application console simple qui déclenchera un workflow capable d’afficher un Nom et un Prénom spécifiés par l’utilisateur.

Evidemment, un projet d’une telle complexité ne nécessite en principe pas l’utilisation d’un workflow, mais cela fait une bonne base de départ avant de se diriger vers des horizons plus sombres.

Conception

1. Création du projet

La première étape, après avoir téléchargé (j’ai mis le lien en fin d’article), installé Windows Workflow Foundation et lancé Visual Studio 2005 est de créer un projet de type workflow (attention, les captures d’écran sont faites avec la beta 1.2 de WWF).

Plusieurs templates sont proposée :

- Sequential Workflow Console Application, celui qui nous intéresse et qui va permettre de créer une application qui à la fois définira et exécutera le workflow. Un workflow séquentiel va permettre de définir une liste d’actions devant s’enchainer.
- Sequential Workflow Library, une DLL qui ne contiendra que le Workflow qui pourra être exécuté/hébergé par une application quelconque (Winform, Webform…).
- Workflow Activity Librairy, qui va permettre de définir vos propres composants d’activités afin de compléter ceux présents par défaut (par exemple définir des déclencheurs d’action sur vos applications existantes).
- State Machine Console Application, qui va vous permettre de modéliser une machine à états, utile par exemple pour des applications de suivit de commande ou de validation.
- State Machine Workflow Library, l’équivalent sans la console.
- Empty Workflow Projet, le bon vieux projet vide qui est souvent la meilleure base de départ.

Pour cette première démonstration, nous utiliserons une application console contenant un workflow séquentiel afin de ne pas soulever de problématique concernant son hébergement et son exécution.

Le projet créé s’ouvre sur un designer, on remarque qu’il contient plusieurs fichiers :

Tout d’abord, un fichier « Program.cs » qui définit l’application console en charge de l’hébergement et de l’exécution de notre workflow. Il s’agira de notre point d’entrée pour envoyer plus tard des paramètres d’initialisation à notre workflow.

Parmi la quinzaine de ligne de code générée automatiquement, on retiendra les plus intéressantes, celles qui vont permettre de déclencher le workflow:

WorkflowRuntime workflowRuntime = new WorkflowRuntime();

En Beta 1.2 :

Type type = typeof(MySimpleWorkflow.Workflow1);
workflowRuntime.StartWorkflow(type);

En Beta 2 :

Type type = typeof(MySimpleWorkflow.Workflow1);
WorkflowInstance instance = workflowRuntime.CreateWorkflow(type);
instance.Start();

On créé le Runtime du workflow, on l’active et on lui demande de démarrer un workflow de type “Workflow1”. Workflow1 correspond au fichier de définition de workflow créé par défaut avec le projet, nous allons nous empresser de changer son nom.

Une fois le nom du fichier changé, il ne faut pas oublier de modifier le type du Workflow que nous souhaitons démarrer dans notre application console : « Type type = typeof(MySimpleWorkflow.MyWorkflow); ». Vous remarquez ici que c’est le nom du fichier qui définit son type.

Le workflow en lui-même est représenté par deux fichiers : un nom.designer.cs qui va contenir les informations de modélisation graphique du workflow, générées automatiquement au fur et à mesure de sa conception ; et un nom.cs qui va lui contenir le code utilisateur (l’endroit ou nous allons pouvoir rajouter nos propres traitements). Les deux fichiers définissent la même classe « MyWorkflow » via un système de classes partielles (nouveauté de .NET 2.0 qui permet de diviser une classe en plusieurs fichiers).
 

Nous pouvons compiler et exécuter le programme, une application console se lance et rien ne se passe, tout fonctionne donc correctement !

2. Ajout d’une activité simple

Nous allons maintenant pouvoir passer à l’étape suivante: envoyer des paramètres à notre Workflow et lui faire exécuter une action en utilisant ceux-ci.

Au niveau de notre application console, il suffit de définir une liste de paramètres à envoyer au démarrage de notre Workflow. Cette liste est représentée par un Dictionnaire contenant des clés (string) et des valeurs (object).

Console.WriteLine("Votre nom");
string nom = Console.ReadLine();
Console.WriteLine("Votre prenom");
string prenom = Console.ReadLine();

Dictionary<string, object> namedArgumentValues =
new Dictionary<string, object>();
namedArgumentValues.Add("nom", nom);
namedArgumentValues.Add("prenom", prenom);

Type type = typeof(MySimpleWorkflow.MyWorkflow);
WorkflowInstance instance = workflowRuntime.CreateWorkflow(type, namedArgumentValues);
instance.Start();

Comme vous pouvez le constater, au moment ou nous allons démarrer notre workflow, nous spécifions en plus du type notre dictionnaire de paramètres.

Il faut maintenant préparer notre Workflow à recevoir nos arguments.

En BETA 1.2 :
Pour ceci, dans le designer de celui-ci, au niveau des propriétés générales du Workflow, on remarque la possibilité de spécifier des paramètres :


Comme vous pouvez le constater, il suffit de définir le nom, le type et la direction de vos paramètres. Pour cet exemple je vais travailler uniquement avec des paramètres d’entrée, donc ayant la direction « In ». Attention à ce niveau de bien respecter la « case » (majuscules/minuscules), que cela soit pour le nom ou le type au risque de tomber sur une erreur du style :
« Unhandled Exception: System.ArgumentException: Workflow Services semantic error: The schedule 'MyWorkflow' has no parameter named 'prenom'.”

En BETA 2:
Il n’est plus possible de définir les variables graphiquement, il suffit de les declarer au niveau du code du Workflow et l’assignation des parameters aux variables se fera automatiquement lors de l’initialisation du Workflow:

private string _nom;

public string nom
{
get { return _nom; }
set { _nom = value; }
}
private string _prenom;

public string prenom
{
get { return _prenom; }
set { _prenom = value; }
}

Il ne nous manque plus qu’a utiliser ces paramètres au niveau de notre workflow. La prochaine étape va donc être de les afficher. Pour ceci, toujours dans notre designer, il va suffire de rajouter une activité de type « Code ».

Vous pouvez ici remarquer qu’il existe de base un petit peu plus d’une 20aine d’activités, dans un prochain article j’illustrerai la facilitée de développer votre propre activité.

Quelques paramétrages vont être nécessaires avant de pouvoir écrire notre bout de code, au niveau des propriétés de notre activité de code :
- Renommer l’ID pour une meilleure compréhension au niveau du designer (ici en AfficheNomPrenom)
- Nommer le bout de code à exécuter en générant un handler : deux solutions sont possibles : cliquer sur generate Handlers en bas des propriétés de l’activité ou aller double clicker sur Execute Code dans son gestionnaire d’événements (ici notre méthode s’appele AfficheNomPrenom_ExecuteCode).

Il ne reste ensuite plus qu’à écrire les lignes de code représentant l’action à entreprendre. A ce niveau on peut imaginer faire tout ce que l’on souhaite, de l’envoie d’Emails à des requêtes dans une base de données en passant par de la génération de fichiers. Pour cet exemple, nous allons nous contenter d’afficher sur la console le nom et le prénom entrés en paramètre.

En BETA 1.2

private void AfficheNomPrenom_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Hello, {1} {0}",
this.Parameters["nom"].Value,
this.Parameters["prenom"].Value);
}

En BETA 2

private void AfficheNomPrenom_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Hello, {0} {1}", nom, prenom);
}

Il ne nous reste plus qu’a exécuter et vérifier que tout fonctionne.

Pour cet exemple le workflow affiche directement sur la console, mais dans la plupart des cas, c’est l’application host qui devra s’occupé d’afficher les valeurs renvoyées par son workflow (donc le fichier Program.cs).

3. Rajout d’une boucle conditionnelle

Pour terminer l’exemple, nous allons rajouter une boucle (while) afin d’afficher plusieurs fois cette phrase. Il suffit d’ajouter à notre workflow une activité de type « while » et de la paramétrer.

Au niveau des conditions, deux possibilités s’offrent à nous :

- Utiliser le gestionnaire graphique de condition (Rules.RuleConditionReference), qui offre un assistant très pratique pour définir sa condition, puis enregistrer cette dernière dans un fichier « rules.xoml » Cette méthode graphique est rapide lorsque vous devez réaliser des conditions simples.

- ou définir une méthode renvoyant un booloean (CodeCondition) chargée de la vérification de la condition. Cette méthode va être plus appropriée pour des vérifications complexes et plus personnalisées.

Malgré le fait que la première méthode soit la plus appropriée, nous allons utiliser la deuxième (la première est bugée dans la Beta 1.2 et empêche la compilation du projet, mais fonctionne sans problème en Beta 2).

Voici donc le bout de code représentant la méthode :

En BETA 1.2

public int compte = 0;

bool checkIfInfCinq(object sender, EventArgs e)
{
if (compte >= 5)
return false;
else
return true;
}

En Beta 2

public int compte = 0;

void checkIfInfCinq(object sender, ConditionalEventArgs e)
{
if (compte <= 5)
{
compte++;
e.Result = true;
}
else
e.Result = false;
}

On peut maintenant lier notre méthode à notre activité:

Voila, il ne reste plus qu’à exécuter une action à chaque tour de ma boucle, pour l’exemple je vais me contenter de re-exécuter la méthode qui affiche le nom et le prénom, en ayant bien sur rajouté à celle-ci une ligne de code afin d’incrémenter mon compteur.

On teste une dernière fois, et tout fonctionne !

C’est terminé, comme vous pouvez le constater, ce n’est pas bien compliqué de faire un workflow simple (et inutile…).

Florent SANTIN