Les colonnes lookup permettent aux éléments d'une liste de référencer un ou plusieurs éléments d'une autre liste, afin de s'approcher du comportement d'une base de données relationnelle dans WSS 3.0. Créer une colonne lookup dans un site éxistant n'est pas particulièrement difficile, mais dans le contexte d'un template de site, on coince car une colonne lookup ne peut être crée que si la liste cible existe : lors de la définition d'un template de site accompagné de templates de listes on ne peut pas connaitre les identifiants qu'auront ses listes une fois créées.
La technique que nous allons voir consiste en une feature qui définit et instancie les 2 listes, puis créé la colonne lookup.
Nous allons réaliser un template de site permettant le suivi des résultats de parties de poker, contenant une liste Parties et une liste Résultats. Un résultat est le gain net d'un joueur (utilisateur membre du site) lors d'une partie, on voudra donc une colonne lookup dans la liste Résultats. On utilisera un projet de type WSPBuilder (installé avec WSPBuilder Extensions) afin de ne pas se préoccuper du packaging et du déploiement, et Sharepoint Site Generator disponible dans le package Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions.
Créons un site vierge avec l'interface classique de Sharepoint, et ajoutons-y les listes et colonnes que l'on souhaite avoir dans notre template. Utilisons ensuite Sharepoint Site Generator pour générer les templates de ces deux listes : Les répertoires Parties et Resultats sont créés.
Création de la feature des templates de liste
Ajoutons à notre projet une feature vierge (via WSPBuilder) de scope Web pour nos templates de liste et copions y les 2 répertoires correspondants fraichement générés. En observant Resultats/schema.xml, on se rend bien compte du problème : la colonne lookup n'a pas pu être définie automatiquement :
Bien que la colonne Partie n'existe pas, les vues (éléments View) la référencent. Gardez cela en mémoire, nous en reparlerons lors de la dernière étape.
Afin que nos deux templates de listes soient inclus dans la feature et instanciés lors de son activation, il faut remplir elements.xml comme ceci :
ListTemplate : Nous devons décider d'un identifiant Type pour chacun de nos templates de liste. Ceux-ci doivent être uniques dans la feature dans laquelle ils sont déclarés. Prenons donc 1 et 2. Hidden="TRUE" permet de ne pas proposer nos templates de liste dans l'écran accessible via le bouton "Create" de WSS. Cliquez ici pour plus d'informations sur l'élément ListTemplate.
ListInstance : L'outil CreateGuid de visual studio nous permet de générer des identifiants pour nos deux instances. la valeur de FeatureId doit correspondre à l'identifiant de la feature générée par WSPBuilder (visible dans feature.xml), et celle de Type doit correspondre celle du ListTemplate correspondant. Cliquez ici pour plus d'informations sur l'élément ListInstance.
Création d'un template de site
Afin de créer un template de site vierge, copions le contenu du template de site de base "sts" (répertoire C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\SiteTemplates) dans notre projet sous 12/TEMPLATE/SiteTemplates/PokerLookup. Ouvrons le fichier onet.xml et dans le noeud <Configuration ID="1" ..> ajoutons une référence vers notre feature :
Ainsi, à chaque fois qu'une instance de notre template de site sera créée, la feature PokerLookup y sera activée, ce qui aura pour résultat la création de nos deux listes.
Le template est prêt, reste à informer Sharepoint qu'il existe. Pour ce faire, Ajoutons à notre projet un fichier 12/TEMPLATE/XXXX/XML/WEBTEMP_PokerLookup.xml, où XXXX est le LCID de la langue dans laquelle le template doit être référencé (1033 pour l'anglais, 1036 pour le francais, etc.). Sharepoint cherche la liste des templates de site à chaque fois qu'il redémarre dans les fichiers WEBTEMP_*.xml de tous les répertoires 12/TEMPLATE/XXXX/XML.
Il faut ensuite référencer la configuration 1 du template de site PokerLookup dans notre fichier WEBTEMP_PokerLookup.xml:
Notre template de site est prêt pour un premier test. A ce stade, la structure du projet est la suivante :
Grâce au menu contextuel offert par WSPBuilder, on peut packager et déployer notre solution. Il est alors possible de créer un site avec notre template de site : les 2 listes apparaissent correctement. Cependant, il manque la colonne lookup Partie dans la liste Résultats pour finaliser notre template.
Ajout de la colonne lookup
Il existe deux moyen de procéder : par code avec un SPFeatureReceiver, et en manipulant le fichier schema.xml.
Ajout d'une colonne lookup par code
Le SPFeatureReceiver permet d'éxécuter du code après qu'une feature soit activée. Créons une classe PokerLookup_Lists, héritant de SPFeatureReceiver, et ajoutons-y le code suivant :
Indiquons dans feature.xml que cette classe est branchée à notre feature :
On notera l'attribut Hidden="TRUE" dont le but est d'éviter que des administrateurs puissent réactiver cette feature, ce qui pourrait poser problème puisque le code de FeatureActivated n'est prévu pour être exécuté qu'une seule fois (afin de ne pas s'éloigner du sujet de ce post).
Si l'on redéploie notre solution et que l'on créé une nouvelle instance de notre template de site, nous constaterons que la colonne Partie est correctement crée. Cependant, elle est présente en double dans les vues définies par notre template de liste. Lors d'une telle implémentation, si on a utilisé Sharepoint Site Generator pour créer les templates de liste, il faut donc retirer "à la main" toutes les références à la colonne lookup dans le fichier schema.xml pour éviter ce problème.
Ajout d'une colonne lookup par XML
Créer un SPFeatureReceiver juste pour ajouter une colonne lookup fait forcément froncer les sourcils au développeur Sharepoint, il existe heureusement une solution XML. La définition du champ Partie (dans Resultats/schema.xml, qui est commentée par Sharepoint Site Generator, est en fait utilisable si on utilise l'attribut List pour spécifier l'url de la liste cible (au lieu de son Id dans son contexte d'origine) :
Bien que le SDK spécifie d'utiliser l'attribut List pour spécifier le nom de la liste cible, il faut bel et bien spécifier l'url. Cliquez ici pour plus d'informations sur l'élément Field.
Conclusion
Les colonnes lookup, indépendantes du concept de template de site, sont plus difficiles à intégrer aux templates de site que les colonnes classiques. Le plus pratique est alors d'utiliser une feature regroupant les deux listes (et leurs templates) concernées.
Déclarer la colonne dans le fichier schema.xml du template de liste permet de centraliser toutes les déclarations de colonnes et rend le template plus maintenable, ne nécessitant pas le déploiement d'une assembly. Mais dans des cas plus complexe où l'url de la liste cible n'est pas toujours connue (colonne lookup cross-site), ou autres cas tordus, il peut s'avérer utile d'utiliser la déclaration par code qui offre plus de possibilités et de souplesse.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :