1. Création du projet
Nous commençons par choisir notre modèle de workflow sous Visual Studio dans la section « SharePoint » comme dans la capture suivante :
Plusieurs modèles sont disponibles, certains correspondent aux workflows pour WSS, d’autres pour MOSS. La liste dépendra donc des SDK présents sur votre machine :
- Sequential Workflow Library : assembly (DLL) contenant un workflow de type séquentiel, c’est celui que nous allons utiliser dans ce tutoriel
- SharePoint Server Sequential Workflow Library : idem que précédemment, mais plus particulièrement pour MOSS 2007
- State Machine Workflow Library : assembly contenant un workfllow de type machine à état
- SharePoint Server State Machine Workflow Library : idem que précédemment, mais plus particulièrement pour MOSS 2007
Pour tous ces workflows, l’hébergement sera effectué par SharePoint. Donc, hormis une installation de SharePoint, nul besoin d’installer des bases de données supplémentaires ou d’enregistrer de services.
Nous choisissons donc le « Sequentiel Workflow Library ». Appelons le projet « WorkflowSimpleSharePoint » et lançons sa création.
Dans l’explorateur de solution, vous devez obtenir un projet contenant les fichiers suivants :
- Feature.xml : fichier XML décrivant notre fonctionnalité et tous les éléments qui seront ajoutés à SharePoint. Ici, notre workflow.
- Install.bat : fichier de batch permettant d’installer et de mettre à jour facilement notre workflow dans SharePoint. Il est à noter cependant que, bien qu’utile et suffisant dans un environnement de développement, le projet final devra être packagé en tant que « solution » SharePoint pour un déploiement propre en production. Cette partie sera brièvement expliquée à la fin de cet article.
- Workflow.xml : fichier XML décrivant notre workflow.
- Workflow1.cs (et le fichier associé Workflow1.designer.cs) : fichier contenant notre classe de workflow.
Rentrons dans le vif du sujet en double-cliquant sur le fichier « Workflow1.cs » pour passer en mode design.
2. Ajout des activités
Tout d’abord, vous observerez une différence entre les workflows « traditionnels » Workflow Foundation et ceux pour SharePoint : la première activité « OnWorkflowActivated1 ».
Cette activité est obligatoire et doit commencer tous vos workflows pour SharePoint.
Nous allons étoffer notre workflow de plusieurs activités par simple « drag ‘n drop » depuis la barre d’outils qui doit comporter les activités de base Workflow Foundation ainsi que celles spécifiques à SharePoint. En effet, SharePoint dispose d’une petite bibliothèque d’activités pour réaliser les actions les plus fréquentes comme l’assignation d’une tâche ou l’envoi d’un email.
Nous allons commencer par rajouter l’activité « IfElse » pour avoir un test conditionnel. Ensuite, nous ajoutons successivement une activité « CreateTask » dans la branche conditionnelle de gauche, puis une activité « While » à sa suite et contenant elle-même une activité « OnTaskChanged ». Vous devriez arriver au résultat suivant :

Les points d’exclamation rouges présents sur plusieurs activités signalent qu’il manque certains paramètres, que nous allons maintenant déclarer.
3. Configuration des activités
Déclarons le test conditionnel du « ifElseBranchActivity1 » en choisissant « Code Condition » et en lui donnant le nom « possedeMotCle ».

Tapez ensuite sur la touche « Entrée », une méthode sera alors générée. Cette méthode sera appelée avant l’exécution de l’activité, c’est donc l’endroit parfait pour déclarer nos paramètres.

Cette méthode reçoit un paramètre « e » de type « ConditionalEventArgs ». Celui-ci possède une propriété « Result » (booléen) qui définit le résultat renvoyé et la réussite ou non du test.
Ajoutez à l’intérieur de cette méthode la ligne suivante :
e.Result = this.workflowProperties.Item.Title != null && this.workflowProperties.Item.Title.ToLower().Contains("rapport");
Nous testons ainsi si le titre de l’élément lié au workflow est non nul et s’il contient le mot clé « rapport ».
Revenez en mode design, et affichez les propriétés de l’activité « createTask1 ». Définissez le jeton de corrélation (« Correlation Token ») comme suit :

Ce jeton est très important car il permet de relier les tâches à l’instance de workflow et à l’environnement qui l’héberge. Il vous faudra donc un jeton unique pour chacune des tâches que vous créerez dans votre workflow et que vous utiliserez pour toutes les activités liées à cette tâche, comme dans notre cas l’activité « onTaskChanged1 ». Modifiez donc cette activité pour qu’elle utilise le même jeton de corrélation « taskToken1 ».
Revenons à notre activité « createTask1 ». Il nous reste encore à définir les paramètres de notre tâche : son titre, sa description, la personne à qui elle est assignée…
Pour cela, nous allons créer une variable « createTask1_TaskProperties1 » représentant les propriétés de la tâche. Allez dans les propriétés de « createTask1 », cliquez sur le bouton « … » des « TaskProperties ».
Une fenêtre apparaît vous proposant de vous lier à un nouveau membre ou à un membre existant. Choisissez « Bind to new member », puis « Create Field » et validez.
« Create Field » crée une variable tandis que « Create Property » crée une propriété. Ce dernier choix vous sera utile si vous souhaitez rendre disponible une propriété à un autre workflow, par exemple.

Maintenant que nous avons défini notre variable, nous allons en définir les valeurs. Nous allons utiliser la méthode appelée lors de l’invocation de l’activité : « MethodInvoking », dans la section « Handlers ». Tapez « creationTache » puis « Entrée » pour générer automatiquement la méthode.

C’est dans cette méthode « creationTache » ainsi créée nous allons définir notre tâche en lui ajoutant les lignes suivantes :
// définition de l'identifiant de la tâche
this.createTask1.TaskId = Guid.NewGuid();
// définition des propriétés de la tâche
this.createTask1_TaskProperties1.Title = "Validation de l'élément";
this.createTask1_TaskProperties1.Description = "Pour valider l'élément, veuillez mettre l'état de la tâche à \"Terminé\".";
this.createTask1_TaskProperties1.AssignedTo = this.workflowProperties.Originator;
Définissons maintenant notre boucle « while ».
Dans le code, ajoutez la déclaration d’un booléen « tacheTerminee » après le constructeur du workflow comme ceci :
private bool tacheTerminee = false;
Repassons en mode design et utilisons cette variable pour l’activité « whileActivity1 ». Pour cela, affichez les propriétés de l’activité, choisissez « Declarative Rule Condition » comme type de condition, puis dans « ConditionName » cliquez sur « … ».
Une fenêtre vous permettant de définir des règles conditionnelles apparaît.

Cliquez sur « New » pour ajouter une règle, et inscrivez-y « !this.tacheTerminee » comme sur la capture suivante :
Validez en cliquant sur « OK », puis « OK » de nouveau dans l’écran de définition des règles. Vous devriez obtenir l’affichage suivant :

Il nous faut maintenant configurer notre activité « onTaskChanged1 » afin de prendre en compte l’état de la tâche une fois modifiée. Affichez les propriétés de cette activité :

Nous allons rajouter une variable qui récupèrera les propriétés de la tâche après la modification. Pour cela nous allons lier la propriété « AfterProperties » à un nouveau membre. Cliquez sur « … » des « AfterProperties », choisissez « Bind to new membre », puis « Create Field » et laissez le nom par défaut « onTaskChanged1_AfterProperties1 ». Validez.

Ajoutons la méthode appelée lors de l’invocation de l’activité : tapez « modifieTache » pour la propriété « Invoked » de la section « Handlers ».

Appuyez sur « Entrée » pour générer la méthode comme ceci :

Rajoutons lui ces quelques lignes :
Guid champEtat = this.workflowProperties.TaskList.Fields.GetFieldByInternalName("Status").Id;
string etat = (string)this.onTaskChanged1_AfterProperties1.ExtendedProperties[champEtat];
this.tacheTerminee = (etat == "Terminé");
Quelques explications sur ce bout de code :
- Certains champs de la tâche sont disponibles directement en tant que propriétés des « AfterProperties », d’autres sont accessibles via les « ExtendedProperties », un ensemble de clé/valeur (« HashTable ») contenant tous les champs. Malheureusement, la clé est l’identifiant (Guid) du champ, ce qui rend sa récupération un peu plus délicate.
- Nous récupérons donc l’identifiant du champ représentant l’état de la tâche en utilisant son nom interne « Status ». Il existe divers moyens de récupérer ce nom interne, le plus simple étant de se rendre dans les paramètres de la liste et de cliquer sur la colonne désirée. Vous verrez alors un paramètre dans l’url « &Field=nominterneduchamp ». En effet, le nom interne peut être différent du nom affiché, il faut donc faire attention à retrouver le bon nom.
- Enfin, nous assignons la valeur de la colonne « Etat » à une variable que nous testons pour voir si elle correspond à la valeur « Terminé » (à modifier selon la localisation de votre site).
4. Ajout d’activités d’historisation
Ajoutons pour finir quelques activités de log (« LogToHistoryList ») afin d’enrichir de quelques commentaires l’historique du workflow.
Plaçons en une juste après le « OnWorkflowActivated1 », une juste avant « createTask1 » et une dans la branche « IfElse » de droite. Renommons-les pour plus de lisibilité respectivement « LogActivation », « LogCreationTache » et « LogMotCleNonTrouve ». Nous allons configurer le message qui sera affiché par chacun en modifiant leur propriété « HistoryDescription » comme ci-dessous :

Mettez les valeurs suivantes (sans les guillemets) :
- LogActivation : « Activation du workflow »
- LogCreationTache : « Mot clé trouvé, création d’une tâche »
- LogMotCleNonTrouve : « Mot clé non trouvé, fin du workflow »
5. Déploiement de votre workflow
Maintenant que notre workflow est fin prêt à être utilisé, il nous faut le déployer dans SharePoint. Pour cela nous allons devoir modifier les 3 autres fichiers présents dans le projet : Feature.xml, Workflow.xml et Install.bat.
Mais avant de faire ces modifications, nous allons avoir besoin de signer notre assembly car elle va être publiée dans le GAC (Global Assembly Cache). De plus, nous devrons aussi récupérer son « PublicKeyToken » généré depuis la clé de signature.
Pour signer notre assembly, faites un clic droit sur le projet, puis « Propriétés ». Là, allez dans l’onglet « Signature » sélectionner « Nouveau »

Dans la fenêtre, entrez le nom de la clé (ici « Workflow » mais n’importe quel nom fera l’affaire), décochez la protection par mot de passe et validez.
A la prochaine génération de votre DLL celle-ci sera signée. Nous reviendrons dessus dans peu de temps.
Modifions le fichier « Feature.xml ». Ce fichier décrit la fonctionnalité que vous allez rendre disponible dans SharePoint. Il référencie le fichier « Workflow.xml » qui lui se charge d’installer votre workflow. Ouvrez le fichier et suivez les indications pour l’insertion du snippet « Feature.xml ». Remplacez ensuite les différentes valeurs comme suit :

Important à savoir : gardez en tête que le langage XML est sensible à la casse, un caractère en majuscule n’est pas la même chose que le même caractère en minuscule. Cette différence est parfois source d’erreurs lors de vos déploiements ou du fonctionnement de votre workflow.
Pour la génération du Guid, vous pouvez utiliser le petit utilitaire fourni avec Visual Studio qui est présent dans le menu « Outils ». Sélectionnez le format base de registre (« Registry Format »). « New GUID » vous permet de générer un nouveau Guid, « Copy » de le copier dans le presse-papiers :


Ouvrez le fichier « Workflow.xml ». Celui-ci définit le comportement et les paramètres de votre workflow. Tout comme pour le fichier « Feature.xml », utilisez le snippet comme décrit dans les commentaires du fichier et remplacez les valeurs comme suit :

Vous devez remplacer le « PublicKeyToken » par celui correspondant à votre assembly signée. Pour cela, générez votre projet pour obtenir la DLL dans le sous-répertoire « bin\Debug » de votre projet et utilisez soit l’utilitaire « Reflector » (lien en fin d’article) ou bien en plaçant votre DLL dans le GAC (drag ‘n drop de la DLL dans le répertoire C:\Windows\Assembly). Nous avons aussi délibérément supprimé certains attributs (urls de gestion de workflow : association, initialisation, modification) car nous n’en avons pas besoin dans cet exemple. Sachez aussi que l’attribut « TaskListContentTypeId » correspond à l’identifiant du type de contenu des tâches associées au workflow, le code « 0x010801 » étant le type « Tâche de workflow ». Vous pouvez imaginer dériver de ce type de contenu pour créer le vôtre, avec des champs supplémentaires ou une interface de saisie personnalisée.

Avec Reflector

Dans le Global Assembly Cache
(vous pouvez afficher les propriétés et copier coller le Public Key Token)
Il ne reste plus qu’à modifier le fichier « Install.bat » pour installer le workflow en tant que Feature. Ouvrez le fichier et effectuer un « chercher / remplacer » du mot « MyFeature » par « WorkflowSimpleSharePoint ». Eventuellement remplacez l’url http://localhost par celle de votre site, le script se chargeant d’activer la Feature pour celui-ci.

Sauvegardez et exécutez le fichier « Install.bat ».
Rendez-vous sur votre site SharePoint.
Dans mon cas, c’est un site d’équipe, mais peu importe le modèle choisi, la procédure reste la même.
Nous allons commencer par vérifier que notre Feature est bien présente. Pour cela, allez dans les « Paramètres du site » depuis les « Actions du site ».

Puis dans la section « Administration de la collection de sites » cliquez sur « Fonctionnalités de la collection de sites ».
Là vous devriez voir parmi la liste des fonctionnalités disponibles pour la collection de sites courante celle que vous venez de déployer.

Nous allons associer notre workflow à notre bibliothèque de documents. Allez dans une des listes ou bibliothèques de votre site, dans mon exemple ce sera la bibliothèque de documents « Documents partagés ». Allez dans les paramètres.

Dans la section « Autorisations et gestion », cliquez sur « Paramètres du flux de travail » (belle traduction mot à mot de workflow !).

Cliquez ensuite sur « Ajouter un workflow » et remplissez la page comme suit :

Nous donnons un petit nom à notre workflow, lui associons une liste de tâches et une liste d’historique. Enfin, nous choisissons de démarrer manuellement le workflow. Nous aurions pu tout autant le démarrer automatiquement sur ajout ou modification d’un élément en cochant les dernières cases.
Nous voilà avec notre workflow associé à la bibliothèque.

Vous pourrez revenir sur cette page pour supprimer ou associer d’autres worklows.
Afin de tester notre workflow, ajoutons un fichier quelconque dans la bibliothèque si vous n’en avez pas déjà. Vérifiez que le titre du document ne contient pas le mot « rapport » (attention, le titre n’est pas le nom du document !). Déroulez ensuite le menu contextuel du fichier pour sélectionner « Workflow ».

S’affichent alors les workflows associés à cet élément. Nous retrouvons notre workflow « Workflow Mot-clé». Cliquez dessus pour le lancer.

Comme nous n’avons pas le mot-clé dans le titre, notre workflow est directement marqué comme « Terminé » (une nouvelle colonne portant le nom du workflow est affichée) et si nous cliquons sur ce lien nous arrivons sur la page d’état du workflow. Nous pouvons ainsi observer l’historique.

Editons notre élément afin de rajouter un titre comportant le mot-clé « rapport », par exemple en rentrant « Rapport de réunion » comme titre du document et relançons le workflow. Cette fois-ci le statut passe à « En cours ». Cliquez sur le lien du statut pour vous retrouver à nouveau sur la page d’état du workflow. Cette fois-ci, nous remarquons qu’il y a une tâche en attente de réalisation et l’historique nous indique que le mot-clé a bien été trouvé.

Déroulez le menu contextuel de la tâche, passez son état à « Terminé » et validez.

Le workflow est alors marqué comme terminé.
Ici prend fin ce tutoriel de création de workflow pour SharePoint à l’aide de Visual Studio 2005.
Au début de l’article, je vous ai parlé de la création de « solution » afin de packager votre workflow. Une solution est un fichier CAB contenant tous les fichiers à installer sur votre ferme automatiquement. Imaginez une sorte de MSI propre à SharePoint. Sachez que les modèles de workflow fournis avec le SDK MOSS 2007 contiennent un script de génération de cette solution. La seule chose à faire pour l’utiliser dans un environnement ne possédant que WSS 3.0 est d’enlever simplement la référence à « Microsoft.Office.Workflow.Tasks » et de suivre les indications dans le script « PostBuildActions.bat ».
Cependant, vous pouvez créer facilement la solution pour le projet que nous avons créée en suivant les étapes suivantes. Je ne détaillerai que sommairement ces étapes.
1. Création du fichier Manifest.xml
Ce fichier définit les éléments qui doivent être ajoutés à SharePoint : features, assemblies, modèles de liste, … Créez donc ce fichier « manifest.xml » à la racine du projet avec le contenu suivant :
<?xml version="1.0" encoding="utf-8" ?>
<Solution xmlns="http://schemas.microsoft.com/sharepoint/"
SolutionId="{8B4B66A4-EAD7-4f23-8C4C-076338FB0BD8}">
<FeatureManifests>
<FeatureManifest Location="WorkflowSimple\Feature.xml"/>
</FeatureManifests>
<Assemblies>
<Assembly Location="WorkflowSimpleSharePoint.dll" DeploymentTarget="GlobalAssemblyCache"/>
</Assemblies>
</Solution>
2. Création du « Diamond Definition File » (fichier ddf)
Ce fichier permet de fournir les paramètres à l’utilitaire « makecab.exe » qui s’occupera de générer le fichier solution. Créez le fichier « solution.ddf » à la racine du projet avec le contenu suivant :
;
.OPTION EXPLICIT ; Generate errors
.Set CabinetNameTemplate=WorkflowSimple.wsp
.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set CompressionType=MSZIP;** All files are compressed in cabinet files
.Set UniqueFiles="ON"
.Set Cabinet=on
.Set DiskDirectory1=Solution
manifest.xml
Feature.xml WorkflowSimple\Feature.xml
Workflow.xml WorkflowSimple\Workflow.xml
bin\Debug\WorkflowSimpleSharePoint.dll WorkflowSimpleSharePoint.dll
3. Génération du fichier de solution
Créez un fichier batch ou bien lancez directement la commande suivante :
« Makecab /F solution.ddf »
Un répertoire « Solution » est créé et contient le fichier « WorkflowSimple.wsp ». Pour l’installer sur notre ferme, il faudra d’abord désinstaller proprement notre précédente installation. Copiez le fichier « install.bat » et renommez le en « uninstall.bat ». Dans ce fichier :
- Mettez en commentaire les lignes 22, 37 et 38 (gacutil –if, stsadm –o installfeature et stsadm –o activatefeature) en rajoutant « :: » devant.
- Décommentez les lignes 34 et 35 (stsadm -o deactivatefeature et –o uninstallfeature)
Lancez le fichier « uninstall.bat ». Pour finir, rendez vous dans le répertoire des features de SharePoint (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\Features par défaut sur un serveur US.
Remplacerz« Common Files » par « Fichiers Communs » sur un serveur français) et supprimez le répertoire « WorkflowSimple ».
Nous sommes prêts à déployer notre solution. Lancez pour cela les commandes suivantes (ajoutez le chemin ….\12\bin dans le path pour vous simplifier l’utilisation de stsadm.exe) :
- « stsadm –o addsolution –filename WorkflowSimple.wsp » pour ajouter la solution dans la ferme
- « stsadm –o deploysolution –name WorkflowSimple.wsp –local –allowGacDeployment » poru déployer la solution. Vous pouvez aussi passer par le site d’administration centrale, dans les opérations / gestion des solutions.
Tous les fichiers ont été déployé sur votre serveur !