Publié dimanche 2 août 2009 12:07 par Arnault Nouvel

SharePoint 2007 : Consommer un web service avec jQuery

 

Background

Je suis récemment intervenu sur un projet SharePoint dans une très grande entreprise. Pour faire court, dans cette entreprise l'équipe intranet en charge de la ferme SharePoint fournit une collection de sites aux équipes métier qui en font la demande. De par l'architecture de SharePoint, l'équipe métier est alors autonome pour gérer sa collection de sites.

Une de ces équipes m'a sollicité pour les aider à la mise en place de leur projet de portail. La collection de sites comprend un sous-site visible par tout les utilisateurs, et un sous-site par pays (chaque utilisateur a accès au site de son pays, + quelques autres pour les responsables par continent) dont l’administration serait déléguée à une équipe dans chaque pays. Mon client m'a donc demandé de développer une page d'accueil dynamique qui proposerait des liens pour chacun des sous-sites accessibles par l'utilisateur courant, avec une mise en forme classique : titre, logo et la description du sous-site.

Sans hésitation, j’explique qu’il suffit de développer une web part dédiée qui utiliserait le modèle objet de SharePoint pour identifier les sous-sites auxquels l’utilisateur a accès, et qu’il y en aurait au grand maximum pour une journée. En effet, dans le cadre de mon intervention de 5 jours, le temps de développement se devait d’être court.

Mon client valide l’idée et je contacte l’équipe intranet pour vérifier que le déploiement d’un package .wsp ne poserait pas de problème. Manque de chance, c’était sans compter sur la longueur de la procédure de validation, en particulier durant cette période des vacances. Nous sommes vite arrivés à la conclusion qu’il était risqué de miser sur un déploiement en production en moins de 5 jours : 

  • Rédaction d’un cahier des charges “officiel”
  • Réunion avec l’équipe intranet pour discuter du cahier des charges et de l’impact du développement sur la ferme
  • Développement et packaging .wsp de la web part en question
  • Revue de code par l’équipe intranet
  • Déploiement en environnement de recette
  • Tests + validation par l’équipe intranet
  • Tests + validation par l’équipe métier (avec la possibilité d’un retour à la case départ)
  • Déploiement en production (nocturne)

Tout cela est 100% justifié : il faut garder à l’esprit qu’un bug ou une faille dans un développement SharePoint, aussi insignifiant soit-il, peut mettre en péril la stabilité de la ferme SharePoint, et l’intégrité des données de la majeure partie de l’intranet. De plus cette procédure devrait être répétée à chaque fois qu’une modification du composant serait nécessaire dans le futur. Le jeu en valait-il vraiment la chandelle ?

Non, surtout qu’en appelant les web services SharePoint par JavaScript, on peut obtenir un résultat équivalent. C’est une approche moins classique, mais qui permet de gagner du temps sur le packaging, le déploiement et la maintenance du composant. L’appel au web service sera grandement facilité par l’utilisation de jQuery, le framework JavaScript à la mode qui dispose d’une méthode dédiée facile d’utilisation, et surtout cross-browser.

 

Implémentation

Avant d’aller plus loin il fallait valider qu’un web service pouvait me fournir les informations dont j’avais besoin. Le SDK de SharePoint 2007 détaille chaque web service disponible : http://msdn.microsoft.com/en-us/library/ms445760.aspx

Webs.asmx dispose d’une méthode GetWebCollection qui retourne la liste des sous-sites du site courant avec leurs titres et url, et GetWeb.asmx retourne le titre, le code langue et la description d’un site donné grâce à l’url passé en paramètre. Bingo !

J’ai référencé dans la master page du site les fichiers JavaScript (celui de jQuery et le mien) placés dans la bibliothèque “Styles Library”, et inséré sur la page d’accueil une web part de contenu éditable contenant :

  • une balise (qui accueillera le menu)
  • une ligne de JavaScript pour exécuter ma méthode de remplissage de cette balise.

CEWP

Pour l’édition du fichier .js, on peut se servir de SharePoint Designer pour naviguer facilement jusqu’à l’emplacement de notre fichier javascript et de le modifier directement, tout en bénéficiant d’une reconnaissance syntaxique du JavaScript.

Ensuite, sur une machine virtuelle MOSS 2007, on peut récupérer l’enveloppe soap correspondante à la méthode que l’on souhaite appeler à l’aide de son navigateur. En l’occurrence, j’ai saisi l’url “http://localhost/_vti_bin/Webs.asmx” dans mon navigateur, et cliqué sur le lien de la méthode GetWebCollection :

Definition

On peut alors écrire la partie JavaScript. La méthode FillMenu() appellera le web service en utilisant l’enveloppe SOAP que l’on vient d’obtenir et remplira le menu. Voici le contenu du fichier JavaScript :

   1:  
   2: var wsWebsUrl;
   3:  
   4: function FillMenu(){
   5:     
   6:     wsWebsUrl = GetWebServiceUrl("Webs.asmx");
   7:     
   8:     if(wsWebsUrl != null){
   9:         
  10:         var request = " \
  11:        \
  12:          \
  13:        \
  14:     ";
  15:       
  16:         $.ajax({
  17:             url: wsWebsUrl,
  18:             type: "POST",
  19:             dataType: "xml",
  20:             data: request,
  21:             success: FillMenu_GetWebCollectionHandler,
  22:             contentType: "text/xml; charset=\"utf-8\"",
  23:             async:true
  24:         });
  25:         
  26:     }
  27: }
  28:  
  29: function FillMenu_GetWebCollectionHandler(response){
  30:     
  31:     var menuRows = "";
  32:  
  33:       // Pour chaque sous élément Web
  34:       $(response).find("Web").each(function() {
  35:          
  36:          var webTitle = $(this).attr("Title");
  37:          
  38:          if(webTitle != "Group"){ //On ne souhaite pas proposer de lien vers Group
  39:              
  40:              var webUrl = $(this).attr("Url");
  41:              
  42:              //récupération des informations relatives au site cible
  43:              var webInfos = FillMenu_GetWebInfos(webUrl)    
  44:              if(webInfos != null){
  45:  
  46:                 var webDescription = $(webInfos).attr("Description");
  47:                 var webLogo = webUrl + "/images/logo.png"; //les logos sont stockée dans chaque site
  48:         
  49:                 // On ajoute une entrée au menu
  50:                 menuRows += " \
  51:                                  \
  52:                                     \
  53:                                          \
  54:                                      \
  55:                                  \
  56:                                  \
  57:                                     " + webTitle + " \
  58:                                     
" + webDescription + "
\
  59:                                  \
  60:                             ";
  61:             }
  62:         }
  63:     });
  64:     
  65:     //on cache, on remplit, et on fait apparaitre le menu avec une animation
  66:     $("#testWS").hide().append(""
+ menuRows + "").slideDown();
  67:  
  68: }
  69:  
  70: function FillMenu_GetWebInfos(webUrl){
  71:     
  72:     var requestWebs = " \
  73:        \
  74:          \
  75:        \
  76:     ";
  77:  
  78:     var returnValue = null;
  79:     
  80:     //appel synchrone qui ne réussit que si l'utilisateur a le droit d'accès au site cible
  81:     $.ajax({
  82:         url: webUrl + "/_vti_bin/Webs.asmx",
  83:         type: "POST",
  84:         dataType: "xml",
  85:         data: requestWebs,      
  86:         contentType: "text/xml; charset=\"utf-8\"",
  87:         async:false,
  88:         success:function(response){
  89:  
  90:                     //construction de la requete soap avec insertion de l'url du site en paramètre
  91:                     var requestWeb = " \
  92:                                        \
  93:                                          \
  94:                                           " + webUrl + " \
  95:                                          \
  96:                                        \
  97:                                     ";
  98:             
  99:                     //appel synchrone pour récupérer les informations du site cible
 100:                     $.ajax({
 101:                         url: wsWebsUrl,
 102:                         type: "POST",
 103:                         dataType: "xml",
 104:                         data: requestWeb,      
 105:                         contentType: "text/xml; charset=\"utf-8\"",
 106:                         success:function(response){
 107:  
 108:                                     returnValue = $(response).find("Web");
 109:                                 },
 110:                         async:false
 111:                     });
 112:  
 113:                 }
 114:         
 115:     });
 116:     
 117:     return returnValue;
 118:  
 119: }
 120:  
 121: // Récupération de l'url du web service dans le contexte du site courant
 122: function GetWebServiceUrl(filename){
 123:         
 124:     //    inspiré par SharePoint Bookmarklets : http://imtech.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=19047
 125:     var UrlPart={Url:0,ServerRelativeUrl:1,Site:2,SiteCollection:3};
 126:     var urlRegex=/^https?:\/\/[^\/]+(((\/(?:sites\/[^\/]+\/)?).*?)((lists\/([^\/]+)|pages|_catalogs|_layouts|_wpresources|_vti_bin|([^\/]+)\/forms|[^\/]+\.aspx).*)?)$/i;
 127:     var url=window.location.href.toLowerCase();
 128:     var match=urlRegex.exec(url);
 129:     
 130:     if( match == null)
 131:         return null
 132:     else
 133:         return match[UrlPart.Site] + "_vti_bin/" + filename;
 134:         
 135: }

On notera l’utilisation d’un appel asynchrone au web service pour la récupération des sous-sites et d’un appel synchrone pour la récupération de la description d’un site. Cet appel synchrone était préférable dans mon cas pour pouvoir remplir ma grille au fur et à mesure.

Voici le résultat :

Capture

Edit : Un appel à GetWebCollection sur chaque sous-site est nécessaire pour déterminer si l’utilisateur courant y a accès.Le security-trimming n’est pas aussi efficace que je le pensais. Le code a été modifié en fonction.

Conclusion

Au final, j’ai gagné un temps fou. Certes, le menu apparait quelques dixièmes de secondes après que la page soit chargée, mais j’ai pu effectuer ce développement sans déployer de code sur la ferme. La maintenance est facilitée, et les risques d’impacts négatifs sur les serveurs sont nuls : Au pire des cas, l’utilisateur aura une erreur JavaScript.

Les web services SharePoint permettent d’obtenir la plupart des informations dont on a besoin lors d’un développement classique, de manipuler les listes, leurs éléments (insertion, modification, suppression), et bien plus encore. Il y a même un web service pour faire de la correction orthographique!

Après avoir vu la vidéo sneak peak de SharePoint 2010 pour les développeurs, en particulier la démo sur l’intégration d’applications Silverlight, on devine que les web services qui composent le “modèle objet client” seront enrichis et améliorés (WCF). On constate que la stratégie de Microsoft est de limiter l’impact d’un développement sur une ferme SharePoint, et de donner plus d’autonomie aux développeurs en réduisant les interactions nécessaires avec les administrateurs de ferme. Les développeurs pourront déployer eux-même leurs applications Silverlight sans risque. En effet, si un développement ne comporte pas de code serveur et qu’il n’interagit avec les données que via des web services qui prennent en compte la sécurité, il n’y a aucun risque pour la santé de la ferme et l’intégrité de ses données. SharePoint pourra alors devenir la plateforme de choix pour toutes les applications intranet, et le coeur du système d’information de l’entreprise.

Il est déjà possible dans SharePoint 2007 d’héberger des applications Silverlight, mais cela nécessite l’intervention d’un administrateur de ferme pour effectuer les modifications nécessaires sur la ferme.

JavaScript est à mon sens l’équivalent dans SharePoint 2007 de ce que sera Silverlight dans SharePoint 2010 en terme de facilité d’intégration. Alors autant s’y mettre tout de suite car les développements 100% client utilisant les web services pour manipuler les données, c’est l’avenir !

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 :

Classé sous , ,

# re: SharePoint 2007 : Consommer un web service avec jQuery @ dimanche 2 août 2009 13:25

hum hum

je suis vraiment partagé.

Techniquement, ok rien à dire bien au contraire

Cependant sur la philosophie, je suis assez surpris pour ne pas dire plus.

le développement qu'il soit client ou server, RIA ou old fashion ne doit pas remplacer un minimum de maintenance ou de régle de gouvernance.

A te lire, on dirait que désormais, on peut coder ce qu'on veut sur un portail sans l'avis de la DSI parceque je n'utilise que le corps client et les WS donc sans risque.

J'ai les droits et SPDesigner, donc c'est open

Ben voyons, le jour que ton composant plante : les utilisateurs sont bloqués, certes moins mais ils n'ont plus leur 'outils'

Donc ils appellent le helpdesk qui répond que personne est au courant, que personne a valide l'utilisation du Jquery, que personne peut en faire la maintenance, ...

Bref, quick and easy certes mais dans la durée, seuls les processus restent.

La notion de validation et de suivi de mise en production a ses raisons certes contraignantes mais elle garantissent que la mise en production durent plus que le temps de présence du consultant, stagiaire ou interimaire du spectacle qui lui, ne sera jamais la pour réparer quand il y a un soucis.

Le truc vraiment drole, c'est que j'ai tenu le même discours en 2001 ou on appellait avec le DDWRT le corps client et qu'on pouvait uploader le code VBscript directement depuis le frontend avec Tahoe,pardon SPS 2001

Certes les technologies evoluent mais ne changent pas le risque, il l'augmente petit à petit en masquant bien des points.

Du code, c'est du code, il impose le même niveau de support et de maintenance surtout dans le cadre d'une entreprise qui centralise ses données

Voila voila

Renaud

themit

# re: SharePoint 2007 : Consommer un web service avec jQuery @ dimanche 2 août 2009 13:30

oh un dernier point dont je viens de me rappeller

http://www.novolocus.com/2008/07/03/browse-directories-and-webs-getwebcollection-strangeness/

>>> le GetWebCollection demande un droit particulier au niveau du profil user "browse directories", donc attention, ca peut être génant pour des users reader only.

Au plaisir

Renaud

themit

# re: SharePoint 2007 : Consommer un web service avec jQuery @ dimanche 2 août 2009 14:31

Bonjour Renaud, et merci pour ton retour.

"le développement qu'il soit client ou server, RIA ou old fashion ne doit pas remplacer un minimum de maintenance ou de régle de gouvernance."

Je ne dis pas le contraire, mais juste que l'équipe métier (qui dispose en l'occurence de compétences javascript) est en mesure d'assurer la maintenance de manière autonome et rapide. C'est ça qui à mes yeux fait la force de cette approche, c'est le point que je voulais mettre en avant dans mon billet.

Il ne s'agit pas d'un développement "à l'arrache", il sera documenté pour l'équipe métier comme le serait un développement .NET, je maintiens toutefois que les administrateurs de la ferme n'auront pas à s'en préoccuper.

Ton deuxième commentaire met en avant un autre avantage des web services SharePoint : l'administrateur de la collection de sites a les pleins pouvoir pour autoriser ou non leur utilisation pour chaque groupe d'utilisateurs, via le système habituel de gestion des permissions, sans avoir à consulter la DSI. Personnellement je trouve ça très utile et en accord avec la philosophie SharePoint visant à déléguer le maximum d'administration aux administrateurs des collections de sites sans pour autant prendre de risque vis à vis de la santé de la ferme.

Arnault Nouvel

# re: SharePoint 2007 : Consommer un web service avec jQuery @ dimanche 2 août 2009 20:31

hum hum, avec plus de détail tout est plus clair pour tout le monde finalement. :)

Une reserve cependant, le droit de browse directories est assez fort au final.

En effet, ca autorise l'utilisation du désormais gratuit et ouvert à tous de ce sympathique outil qu'est SharePoint Designer

...

http://blogs.msdn.com/sharepointdesigner/archive/2008/11/25/locking-down-sharepoint-designer.aspx

Il faut bien ponderer l'attribution de ce droit par défaut au reader/contributeur car les admins metier peuvent avoit la delegation de gestion sans pour autant avoir le recul de ponderer certaines options.

La clairement, il s'agit d'une elevation de droit non négligeable, il faudrait pouvoir le ponderer/mesurer pour que ca ne permet pas trop de liberté.

"La liberté des uns s'arrête là où commence celle des autres"

themit

# re: SharePoint 2007 : Consommer un web service avec jQuery @ mercredi 5 août 2009 15:35

Mouais, pour ma part, je suis tout autant mitigé si ce n'est plus.

Tout d'abord, l'utilisation de ces fonctionnements à la mode est fortement dépendant des navigateurs, et donc des config clients.

Pour donner un exemple, notre Browser officiel est IE6, et dieu sait que le support JS/CSS n'est pas le meilleur avec celui-ci

De plus, la stabilité de cette couche cliente est toute relative et lorsque les postes clients se retrouvent avec un navigateurs parasité par des composants tiers, ce genre de code peut tout d'un coup simplement ne pus fonctionner

De plus, je rejoins totalement Renaud sur le point de la maintenance de cette conception. Il est clair que le role tenu dans ce contexte est le meilleur et quelque part le plus simple, car la solution convient à la demande formulée par le client.

Cependant, en terme de maintenance dans le temps, c'est une des solutions les plus dangereuses pour la pérénité de cette ferme. En effêt, la création de ce type de page implique donc du "Custom Code" au sein même de la page ASPX, qui va donc entrainer une disparité en terme de structuration avec le reste de la ferme.

Ainsi, la structure cliente qui a émis cette demande peut être ammenée à évoluer et la compétence notée comme existante peut être ammenée à disparaître au profit de l'équipe globale IT infra et dév (cas classique de restructuration des équipes). De ce fait, les éventuels corrections deviendront donc très pénibles pour ces personnes.

Devant gérer ce genre de cas en interne, je peux dire que les exotismes de ce type sont une calamité pour moi.

Enfin, le dernier cas et non le moindre est la problématique de la migration. SharePoint est un produit évolutif et il faut toujours penser à ce changement de version lors de ces modification :

- Est-ce dangereux lors de la migration ?

- Vais-je ajouter des risques de non possibilité ?

- ...

Voila quelques points à garder en tête avant de se lancer dans ce type de modification qui paraît miraculeux à première vue mais fait entrer les gestionnaires de fermes SharePoint dans l'enfer.

Pour information, ce type de développement ne serait pas accepté par mes soins, ou avec une signature du sang de ce développeur :))

Romelard Fabrice [MVP]

ROMELARD Fabrice

# re: SharePoint 2007 : Consommer un web service avec jQuery @ jeudi 6 août 2009 15:03

Bonjour Fabrice,

merci pour ton retour aussi surprenant soit-il.

Je parle ici d'une grosse ferme dans laquelle ce sont les équipes métiers qui sont responsables du contenu et des développements liés à leurs collections de sites, et l'équipe intranet qui est responsable du bon fonctionnement et de l'infrastructure de la ferme, pas plus.

Dans ce contexte, pourquoi l'administrateur de la ferme serait-il en droit de contester l'utilisation de jQuery ?

- Cela n'impacte pas les autres collections de sites de la ferme.

- Cela n'impacte pas la santé de la ferme

Pourquoi brider les possibilités de SharePoint, en terme de productivité, qui sont décuplées par l'utilisation des développements clients ? jQuery, Ajax, Silverlight, même combat..

Je ne suis pas d'accord quand tu dis que c'est une solution dangereuse pour la pérénité de la ferme : à mon sens, le risque est tout simplement nul.

De plus, le code spécifique est plus facilement maintenable par l'équipe métier si il s'agit de JavaScript que de code serveur, même dans un contexte de migration.

Les mécanismes de versionning, d'archivage et d'approbation pouvant être appliqués aux fichiers javascript, je trouve ce type de développement (et sa mise en oeuvre) particulièrement élégant.

Tu évoques les risques liés à la compatibilité avec les différents navigateurs, mais les frameworks mentionnés sont notamment utilisés pour palier à cette problématique..

Evidemment on n'est jamais à l'abris d'un changement de rendu css ou d'une incompatibilité du Framework lors d'une nouvelle version de navigateur, mais je pense qu'il s'agît d'un faux problème : il  serait le même avec un développement .wsp validé par l'équipe intranet. Je me souviens avoir du repasser sur tous mes sites MCMS 2002 lors de la sortie d'IE7 pour corriger les différences CSS.

De plus, si le cas se présente avec jQuery, il suffira à priori de mettre à jour le fichier javascript du framework.

N'oublions pas que Microsoft supportera jQuery dès la sortie de Visual Studio 2010, preuve que cette technologie n'est pas dénuée de sens.

---

Pour en revenir à mon PoC, vu les problèmes inattendus liés au security-trimming de GetWebCollection et GetWebs qui m'obligent à appeller trop de fois le web service, je réflechis actuellement à une autre solution. Cela engendre trop de requêtes à mon goût..

Après avoir lu vos commentaires, je réalise que j'aurais du présenter ce billet avec un exemple basé sur Lists.asmx pour l'ajout/modification d'éléments de liste, ou peut-être Search.asmx, sur un cas d'école. Peut-être que cette approche aurait été plus parlante et mieux mise en valeur.

Quoi qu'il en soit, je reste à 300% convaincu de l'utilité du couple javascript/webservice dans SharePoint.

Arnault Nouvel

# re: SharePoint 2007 : Consommer un web service avec jQuery @ jeudi 6 août 2009 16:40

Je comprends ton point de vue qui est celui du développeur dans l'environnement SharePoint.

Je respecte totalement celui-ci, mais pour ma part et devant gérer les fermes après des interventions potentielles de prestation / stage / interne IT un peu zélé / ..., le résultat peut être compliqué lors de tache de maintenance, tel que des Service Pack qui modifient des paramètres internes de liste (Cf SP2 de 2007) ou encore dans le cadre de migration qu'il va forcément falloir évaluer pour 2010.

Bref, ce sont deux points de vue qui se respectent, mais souvent s'opposent.

Enfin, comme je te l'ai expliqué juste avant ton contexte est dans un état donné aujourd'hui, mais l'organisation peut totalement changer dans quelques temps et les ressources que tu connais disparaître.

ROMELARD Fabrice


Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01