SharePoint 2010 et IIS 7.0 : URL rewriting pour un site public internet

sharepoint-server

Les fanatiques du référencement le savent, la profondeur des url a un impact sur le référencement naturel. Dans SharePoint, les pages d’un site de publication étant situées dans une bibliothèque “Pages”, les url sont sous la forme http://www.monsite.com/sous-site/Pages/ma-page.aspx et ont donc un niveau d’arborescence inutile voir polluant d’un point de vue référencement.

Dans le cadre d’un projet de site internet hébergé sur SharePoint 2010, on m’a demandé de réfléchir à une solution d’url rewriting pour faire disparaitre /Pages/ de l’url.

Le challenge dans cette tâche était de la réaliser sans apporter de contrainte pour les auteurs du site et surtout sans impacter le fonctionnement de SharePoint.

C’est alors que j’ai découvert le plug-in Url Rewrite (actuellement en RC v2.0) pour IIS 7.0. Celui-ci a pour particularité de permettre l’url rewriting en entrée et en sortie via des règles équivalentes à des replace().

 

Afin de ne pas impacter le “back-office” de SharePoint, on peut étendre la web application (interne) et configurer Url Rewrite sur une 2ème web application (publique).

Les 2 web applications reposent alors sur la même base de données de contenu mais sont configurables indépendamment l’une de l’autre au niveau IIS :

  • http://edit.monsite.com (Zone Default) l’application utilisée par les auteurs, accessible depuis le réseau de l’entreprise. On ne modifie pas la configuration de cette web app. 
  • http://www.monsite.com (Zone Internet) l’application publique pour les internautes, sur laquelle on désactive l’authentification Windows. C’est sur celle-ci que l’on configure Url Rewriter.

Une fois Url Rewriter RC v2.0 installé, lorsqu’on sélectionne un site dans IIS, une nouvelle icone apparait permettant d’accéder à l’interface de paramétrage d’url rewriting.

IIS Url rewrite

 

L’interface de paramétrage permet de définir des règles pour le rewriting d’entrée et le rewriting de sortie basées sur des expressions régulières :

url rewrite

 

Inbound rules

La liste du haut permet de spécifier les règles de redirection selon l’url requêtée. Seule la partie relative au site est testée.

Par exemple pour  http://www.monsite.com/site1/site2/default.aspx, c’est la chaine “site1/site2/default.aspx” qui est testée avec nos expressions régulière. Lorsqu’un utilisateur requête l’application IIS, les règles sont testées (et appliquées en cas de succès) dans l’ordre affiché. En l’occurrence, nous pouvons transformer cette adresse en http://www.monsite.com/site1/site2/Pages/default.aspx, la véritable url de la page que sait interpréter SharePoint.

Dans la capture d’écran, la première règle correspond au cas de la chaine vide. Son rôle est que si l’internaute requête http://www.monsite.com, c’est la page http://www.monsite.com/Pages/default.aspx qui sera servie sans pour autant rediriger l’utilisateur via un code 302. C’est un cas particulier pour la page d’accueil.

La deuxième règle correspond au cas d’une page située dans une bibliothèque de pages (contient /Pages/). Dans ce cas l’url n’a pas besoin d’être réécrite puisqu’il s’agit du cas '”natif”, d’où le Action Type = None.

La troisième règle correspond au cas d’une page située dans /_layouts/. Là encore, on ne modifie pas l’url.

Enfin, la 4ème règle permet de convertir une url http://www.monsite.com/site1/default.aspx en http://www.monsite.com/site1/Pages/default.aspx. Les balises {R:1} et {R:2} correspondent aux groupes matchés par l’expression régulière, équivalent de $1 et $2 dans les langages classiques.

Grâce à ces 4 règles, on bénéficie d’un Url Rewriting satisfaisant permettant d’accéder aux pages de publication SharePoint sans préciser /Pages/ dans l’url, pour un référencement plus efficace.

Récapitulatif des règles d’entrée

Pattern Action Type Rewrite Stop Processing
^$ Rewrite Pages/default.aspx True
(.*/)?pages/.* None   True
(.*/)?_layouts/.* None   True
^(.*/)?([^\/]*?\.aspx)$ Rewrite {R:1}Pages/{R:2} True

 

Outbound rules

Maintenant la partie la plus fun, et la nouveauté de la RC 2.0 de Url Rewriter : le rewriting de sortie !

Les règles du 2ème bloc (de la capture plus haut) permettent de modifier le contenu HTML d’une page servie par l’application avant qu’elle ne soit renvoyée à l’utilisateur. Ce mécanisme permet de supprimer /Pages/ de toutes les url trouvées dans la réponse HTML.

Attention cependant, ce “filtre” s’applique sur tout ce qui est renvoyé par le site web. Cela inclut les images, les scripts, les fichiers… Si on ne limite pas le périmètre de notre transformation aux seuls fichiers HTML, on s’expose à des erreurs serveur.

On va donc configurer une pré-condition permettant de limiter le périmètre de notre transformation aux réponses http dont le content type  commence par “text/HTML”, comme ceci :

HTML pre-condition

Une fois notre pré-condition configurée, on peut configurer notre rewriting de sortie :

image

 

Cette règle se veut très simple afin de limiter l’impact sur les performances : le processus de transformation en sortie étant gourmand en ressources, plus notre expression régulière sera simple, plus l’impact sur les performances sera faible. Cette règle va donc transformer toutes les occurrences de /Pages/nom-de-page.aspx en /nom-de-page.aspx sans se préoccuper du fait qu’il s’agisse ou non d’une url. Attention donc aux cas particuliers :)

Dans mon cas, je ne souhaite pas seulement modifier les url des liens mais aussi les url sous forme de texte, pour modifier l’affichage des résultats de recherche par exemple. Pour limiter la transformation aux liens, j’aurais pu utiliser un filtre prévu à cet effet (“Match the content within:” sur la capture ci-dessus) afin de gagner en performances.

Une dernière chose importante, d’après mes tests il faut désactiver la compression dynamique sur le site IIS sous peine d’erreurs serveur.

Règle de sortie

Pattern Action Type Rewrite
/Pages/([^\s\.]*?\.aspx) Rewrite /{R:1}

 

Conclusion

L’impact sur les performances n’est pas négligeable (traitement supplémentaire + incompatibilité avec la compression dynamique), mais dans un cas où le référencement est stratégique cette solution s’avère efficace et relativement simple à mettre en place. Sa principale force est d’être 100% transparente pour l’application SharePoint.

Compatible avec SharePoint 2007 et SharePoint 2010,  le réel pré-requis est IIS 7.0.

Des tests de montée en charge étant prévus dans les semaines à venir, je ne manquerai pas de publier un retour d’expérience sur cette solution.

TechDays 2010 : Les slides de la session migration SharePoint 2010

sharepoint-server

Comme promis lors de la session “Quel plan de migration prévoir de SharePoint 2007 vers SharePoint 2010”, voici le lien pour télécharger les slides de notre présentation :

Techdays 2010 - Migration SharePoint 2010.pptx

Besoin d’assistance pour préparer la migration vos fermes vers SharePoint 2010 ? N’hésitez pas à nous contacter Antoine Dongois et moi.


Classé sous ,

TechDays 2010 : Migration de MOSS 2007 à SharePoint Server 2010

sharepoint-server

Mardi 9 février à 11H lors des TechDays 2010, avec mon collègue Antoine Dongois, j'aurai le plaisir de co-animer la session "Quel plan de migration prévoir de SharePoint 2007 à SharePoint 2010"

Nous y décrirons les différents chemins de migration possibles avec leurs avantages et leurs inconvénients, et ferons une démo de migration de type DB Attach de bout en bout.

Rendez-vous aux TechDays!

SharePoint 2010 : Utiliser le modèle objet dans un exécutable

sharepoint-server

 

Lorsqu’on essaie pour la première fois d’utiliser le modèle objet de SharePoint 2010 dans une application console ou autre exécutable .NET classique, l’aventure peut commencer par l’erreur FileNotFoundException suivante :

error2

 

Ce problème est normal : par défaut, Visual Studio configure la plupart des projets pour une plateforme x86. Mais pour utiliser le modèle objet de SharePoint 2010, un projet devra être configuré pour une plateforme x64.

Cela se configure en quelques clics. Voici comment faire :

 

solution-explorer

Dans le Solution Explorer, un clic-droit sur le nœud de la solution, puis Configuration Manager.

 

configuration-manager

On crée ensuite une nouvelle “Platform” via le bouton New…

 

configuration-manager2

La fenêtre propose alors de créer une plateforme “Any CPU” (compatible x64), on peut valider sans rien changer.

 

configuration-manager3

Le projet est maintenant correctement configuré, relançons l’application pour tester.

 

success

L’objet SPSite s’instancie maintenant correctement.

 

Ce problème n’est pas seulement lié à la classe SPSite. En pratique, la première fois que j’ai eu ce problème, c’était avec un appel à SPFarm.Local qui renvoyait null si le projet est configuré en x86.

Selon le type d’objet que l’on cherche à manipuler, on aura donc soit une référence nulle, soit une erreur lors de l’instanciation.

Dans les deux cas, rien n’indique au développeur que le problème est lié à la configuration de plateforme du projet. Il devra donc en avoir conscience pour exploiter le modèle objet dans un projet “non-SharePoint”.

Heureusement, les nouveautés de SharePoint 2010 ainsi que les nouvelles possibilités offertes par Visual Studio 2010 pour le développeur SharePoint feront vite oublier ce petit désagrément :)

 

Arnault Nouvel

SharePoint 2007 : jQuery.SPItemsRotator pour afficher des éléments de listes avec animation

 

Avoir des sites “qui bougent” est une demande récurrente des utilisateurs qui s’occupent de la mise en place de sites SharePoint. Il est vrai qu’à l’heure du web 2.0, on s’attend à voir de belles animations dans nos navigateurs, même dans un intranet.

Si on souhaite avoir des éléments de liste qui apparaissent les uns après les autres avec un fondu, on peut procéder de différentes manières :

  • Avec une web part avec code serveur + javascript, ce qui implique le déploiement d’un package sur le serveur
  • Avec une DataView web part + javascript, ce qui n’est pas toujours simple à mettre en place, surtout pour un utilisateur final
  • Avec du javascript uniquement, avec accès aux données par web service. Ce n’est pas optimal d’un point de vue performances, mais permet une intégration rapide si la solution est générique et clé-en-main. 
  • Je passe volontairement sur l’option Silverlight qui est encore plus contraignante dans SharePoint 2007

Le plug-in jQuery.SPItemsRotator correspond à la 3ème option. Il s’intègre en quelques minutes et permet d’afficher les éléments d’une liste d’annonce standard ou d’une bibliothèque d’images standard, avec des fondus entre chaque élément ou image. Ceci ne requiert pas le déploiement de package sur la ferme, tout se fait avec SharePoint designer. Attention cependant, pour les sites publics internet il est vaut mieux choisir les options 1 ou 2 pour des raisons de performances et de sécurité.

jQuery.SPItemsRotator s’appuie sur jQuery et jQuery.SPServices, un plug-in jQuery qui propose une API pour les web services SharePoint. Il est très utile et bien pensé, je ne peux que vous encourager à y jeter un œil.

Après avoir référencé les 3 fichiers JavaScript dans la master page du site à l’aide de SharePoint Designer, on peut placer des jParts (le terme à la mode) pour obtenir quelque-chose comme ceci :

Les jParts sont en pratique des Content Editor Web Parts qui contiennent du code HTML et jQuery :

<!-- Web Part de gauche -->
<div id="divAnnouncements" style="height:150px;"></style>
<script>
   $(window).ready(function(){                                
           $("#divAnnouncements").rotateAnnouncements({
            webURL:"/sites/spitemsrotator", //url du site
            listName:"My Announcements" //nom de la liste
      });
   });
</script>
<!-- Web Part de droite -->
<div id="divPictures" style="height:200px;"></style>
<script>
   $(window).ready(function(){                                
         $("#divPictures").rotatePictures({
            webURL:"/sites/spitemsrotator",
            listName:"My Pictures",
            fadeDuration:1500, //durée du fading en millisecondes
            displayDuration:5000 //durée d'affichage de chaque élément en millisecondes
      });
   });
</script>

Voilà pour l’utilisation basique des méthodes rotatePictures et rotateAnnouncements.

Celles-ci définisse une requête CAML et un formatage précis puis appellent rotateItems, la méthode principale. Un développeur ou un utilisateur avancé peut aussi appeler cette méthode pour afficher et filtrer les éléments en spécifiant la requête CAML, et les formater comme il veut en décidant du pattern de rendu.

Pour exemple prenons le code de rotateAnnouncements, qui peut servir de source d’inspiration pour écrire d’autres rotateXXXXX() méthodes :

jQuery.fn.rotateAnnouncements = function(options){

    var opts = $.extend({
        displayDuration:10000,
        fadeDuration:1500,
        CAMLViewFields:"<ViewFields><FieldRef Name='Body' /></ViewFields>",
        CAMLQuery:"<Query><Where><Or><IsNull><FieldRef Name='Expires' /></IsNull><Geq><FieldRef Name='Expires' /><Value Type='DateTime'><Today /></Value></Geq></Or></Where></Query>",    
        itemHtml:"{ows_Body}"
    }, options);

    return this.rotateItems(opts);
    
}

Un dernier avantage, il est aussi facile de placer la zone de rotation dans une page que dans la master page : au lieu d’utiliser une Content Editor Web Part, on peut placer le HTML+script directement dans la master page avec SharePoint Designer.

Bonnes rotations :)

SharePoint 2007 : Nouvelle version de WSPCompare

Je me suis récemment surpris à utiliser WSPCompare uniquement pour regarder le contenu d’un package .wsp. Suite à ce constat, j’ai publié une nouvelle version de WSPCompare qui dispose d’une interface plus appropriée à ce type d’utilisation.

L’outil propose donc maintenant 2 modes d’utilisation.

Mode navigation si 1 package est ouvert

Browse

Mode comparaison si 2 packages sont ouverts

Compare

 

Je me suis aussi amusé à réaliser une petite vidéo de présentation de l’outil :

 

Pour télécharger WSPCompare, c’est par ici : http://wspcompare.codeplex.com


Classé sous , , ,

SharePoint 2007 : WSPCompare

Il arrive parfois d’avoir besoin de comparer 2 versions d’un package .wsp pour SharePoint, par exemple après le refactoring d’une solution, ou lors de la mise en place d’un build TFS.

L’objectif est en général de vérifier qu’aucun fichier n’a été oublié, et que le manifest.xml est cohérent.

J’ai donc développé WSPCompare, un outil permettant de comparer le contenu de 2 solutions SharePoint. Celui-ci est comme d’habitude publié sur CodePlex.

Après avoir sélectionné les 2 fichiers .wsp à comparer, l’outil présente la liste de tous les fichiers trouvés, en utilisant un code couleur pour identifier les différences :

WSPCompareSummary

L’onglet Détails permet de visualiser le contenu des fichiers pour pouvoir les comparer :

WSPCompareDetails

Pour les téléchargements, c’est par ici : http://wspcompare.codeplex.com/Release/ProjectReleases.aspx


Classé sous , , ,

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 !


Classé sous , ,

MOSS 2007 : jQuery picture viewer Web Part

Récemment, un client m’a demandé de lui développer une web part qui afficherait une bibliothèque d’images sous forme de miniatures, permettant de les télécharger, et de les visualiser en taille réelle via un click de souris.

Ces spécifications m’ont rappelé une superbe démonstration d’Aurélien Verla sur jQuery lors de sa présentation Découverte des nouveautés d'ASP.NET 4.0 aux TechDays 2009.

J’ai donc souhaité intégrer cela dans MOSS 2007, en utilisant la puissance de la Content by Query Web Part (CQWP) afin de bénéficier de fonctionnalités de tri et de filtrage sur les images affichées. Le tout est bien sûr réalisable entièrement dans SharePoint Designer, mais l’envie m’a pris d’aller un peu plus loin que les spécifications initiales et, pourquoi pas, publier ce projet sur CodePlex.

Lien : MOSS 2007 jQuery picture viewer Web Part

Capture

 

Pour avoir la possibilité de télécharger les images, au lieu de les ouvrir simplement dans Internet Explorer, la web part réutilise la page /_layouts/download.aspx, qui existe nativement dans SharePoint. Elle permet de télécharger un fichier dont l’url est passé dans la query string.

Exemple : http://office12-server/sites/t1/_layouts/download.aspx?sourceUrl=http://office12-server/sites/t1/Picture%20Library/Tree.jpg

Cette url renvoie le fichier Tree.jpg de la bibliothèque d’image “Picture Library” située dans la collection de sites http://office12-server/Sites/t1

 

Comme dit plus haut, il est possible de faire la même chose sans déployer de package sur la ferme. Ce développement est ainsi packagé afin de rendre la taille des miniatures paramétrable, de laisser la possibilité de désactiver les animations jQuery, et de pouvoir utiliser 2 fois la web part sur une même page avec un paramétrage différent.

Un développeur MOSS pourrait donc télécharger les sources et utiliser les fichiers .xsl, .js et .css pour intégrer la web part avec SharePoint Designer. Cela ne nécessiterait ni le déploiement de package sur le serveur, ni l’accord de l’administrateur de la ferme :)
A peu de choses près, il suffirait de modifier le fichier JavaScript afin qu’il s’initialise automatiquement, sans appel généré par du code serveur.

SharePoint 2007 : WSPDownload

Après BlobCacheAdmin, je vous propose aujourd’hui une nouvelle page d’administration pour l’administration centrale de SharePoint.

Inspirée par le post de Kype, cette page permet aux administrateurs de télécharger les solutions packages .wsp présents dans le solution store d’une ferme SharePoint.

Après installation de WSPDownload.wsp, un nouveau lien apparaitra dans l’onglet Operations de l’administration centrale :

WSPDownloadLink WSPDownloadForm 

Vous pourrez alors cliquer sur un des solution packages pour le télécharger.

Cet outil est disponible au téléchargement sur CodePlex dans le projet SharePoint Administrator Packages : http://spadminpack.codeplex.com

SharePoint 2007 : BlobCacheAdmin - Page d’administration du Blob Cache

Le Blob Cache permet d’utiliser du cache disque dans les sites SharePoint, ce qui évite des aller-retours avec la base de données pour la récupération de fichiers images, videos, ou autres. Il repose sur une ligne de configuration qu’il fallait jusqu’ici modifier à la main dans le fichier Web.Config de chaque serveur frontal, avec le risque d’erreur que cela induit.

J’ai développé une page d’administration pour permettre à un administrateur de définir ce paramétrage directement dans la Central Administration de SharePoint. Celle-ci utilise la classe SPWebConfigModification, afin que tous les serveurs frontaux soient mis à jour automatiquement. Comme l’explique Sébastien dans son post Gestion des Applications Web SharePoint et sites IIS : Best Practices, cela permet aussi que de nouveaux serveurs ajoutés à la ferme soient mis à jour automatiquement.

Disponible sur CodePlex, BlobCacheAdmin.wsp met à disposition une nouvelle page dans la Central Administration :

Lien dans la page Application Management
BlobCacheAdminLink

Page d’administration du Blob Cache
BlobCacheAdmin

Ce package est le premier de mon nouveau projet CodePlex, SharePoint Administrator Packages, qui réunira plusieurs outils d’administrations.

SharePoint : Optimiser le temps de développement et packager avec WSPBuilder

Ce post a pour but de présenter la manière dont je travaille au quotidien sur mes projets SharePoint, qui s'appuie sur l'outil WSPBuilder (la version en ligne de commande).
Il fait suite à un projet de démonstration que j'ai réalisé avec Visual Studio 2005 dans le cadre d'une formation sur le développement SharePoint. Il contient quelques features et peut servir de modèle lors du démarrage d'un projet SharePoint. Je le propose donc au téléchargement :
DemoWSP.zip

Un projet SharePoint qui se respecte doit  être livré sous la forme d'un SharePoint Solution Package, afin de pouvoir être déployé sur une ferme SharePoint par son administrateur.
Si on attend la fin du développement avant de s'intéresser au packaging, on risque d'aboutir à un refactoring couteux en temps, une solution en forme de plat de spaghettis, et une facture d'aspirines salée.
Alors que si on pense dès le début du projet à la problématique du packaging, la solution sera plus propre, et on gagnera en temps de développement et de maintenance. C’est là qu’intervient la magie de WSPBuilder, outil open source permettant d'automatiser le packaging d'un développement SharePoint.

L'avantage principal de WSPBuilder par rapport aux extensions Visual Studio pour WSS (qui de manière transparente génèrent un package et le déploient à chaque fois qu’on presse F5) est que le développeur exerce un réel contrôle sur la structure et le contenu de son package. De plus, ce modèle permet le déploiement de fichiers dans des répertoires non supportés par les extensions visual studio pour WSS: 12\Resources, 12\TEMPLATE\LAYOUTS, 12\TEMPLATE\IMAGES, etc.

Bien que WSPBuilder soit indépendant de Visual Studio (dans sa version en ligne de commande), la manière la plus pratique de l'utiliser est de créer un projet vide dans Visual Studio (qu'on appellera projet de packaging) dans lequel on créé 3 répertoires :
- un répertoire "12" qui aura la même structure de sous répertoire que celle du répertoire 12 de SharePoint,
- un répertoire "GAC" dans lequel iront les assemblii à déployer dans le GAC,
- et un répertoire "80" dans lequel iront les fichiers à déployer dans les répertoires des web applications.

Chacun de ces répertoires est optionnel, mais dans la majorité des cas on aura besoin des répertoires "12" et "GAC". Il suffit alors d'exécuter WSPBuilder.exe dans le répertoire du projet de packaging pour générer le package .wsp.
Note : Il est conseillé de renommer le package en .cab et de vérifier son contenu, car il peut arriver que WSPBuilder ne produise pas le résultat attendu. Il faut alors utiliser la méthode traditionnelle : création manuelle du .ddf et manifest.xml. Cela m'est arrivé une seule fois, c'est donc très rare, d’ailleurs je pense que le problème a été corrigé dans une des dernières versions de l’outil.

De par la simplicité d'utilisation de WSPBuilder, il n'est pas rare de trouver en entreprise des projets qui l'exécutent directement dans le build-event du projet.
Cela a deux avantages :
- après chaque compilation, un package à jour est généré et il suffit de le déployer via STSADM pour le tester.
- Si on travaille avec Team System, Il suffit dans le team build d'indiquer la solution cible pour que le package .wsp soit généré à chaque compilation, sans paramétrage supplémentaire. Ca, c’est génial.

Malheureusement, en phase de développement il y a de sérieux désavantages :
- Chaque compilation déclenche une génération du package ce qui prend beaucoup plus de temps
- Il faut ensuite déployer le package via STSADM ce qui prend aussi pas mal de temps

Je vais présenter ici la manière dont je travaille, qui permet d'optimiser le temps d'attente entre le moment de la compilation du projet et le moment où on en apprécie le résultat dans son navigateur web, tout en bénéficiant des avantages de WSPBuilder.
L'idée est de faire un déploiement "manuel" en phase de développement pour minimiser le temps d'attente, et de n'utiliser WSPBuilder que lors d'une compilation en mode Release (pour les team builds, et de temps en temps pendant la phase de développement pour ne pas avoir à modifier le fichier web.config de la web application à la main).
Ce modèle requiert un temps de préparation pour organiser la solution et créer les scripts au début du projet, mais le gain de productivité pour la suite est appréciable. Les temps d'attentes entre les déploiements et les tests seront réduit au strict minimum.
 

Solution


La solution Visual Studio comprendra 3 projets de type class library :

- DemoWSP : Le projet de packaging qui servira de structure de répertoires conforme à ce qu'attend WSPBuilder. Il contient les fichiers à déployer dans répertoire 12 (features, resources, etc.), un répertoire GAC et un répertoire 80.
- DemoGAC qui produit une assembly signée (contenant le code applicatif), vouée à être déployée dans le GAC.
- Demo80 qui produit une assembly non signée (contenant le code des web parts), vouée à être déployée dans le répertoire bin de la web application. 

Afin de s'assurer que notre projet pourra être compilé sur un serveur TFS, on prévoit un répertoire Lib dans le répertoire de notre solution, on y place les assemblii SharePoint, et on les référence dans nos projets à partir de ce répertoire Lib.
On devra aussi installer WSPBuilder sur le serveur TFS dans le même répertoire que sur nos machines virtuelles de développement (ou le mettre lui aussi dans le répertoire Lib).

A gauche, une capture d’écran de la structure de ma solution.

 

Le projet de packaging dispose d'un build-event qui appelle CreatePackage.bat lors d'une compilation en mode Release :

BuildEvents

En phase de développement, j'utilise deux scripts situés à la racine du projet de packaging:
- QuickDeploy.bat qui effectue un déploiement complet, copiant chaque fichier au bon endroit et recyclant ma pool d'application. Il met environ 1 seconde à s'exécuter, énorme gain comparé à la méthode consistant à générer puis déployer le package.
- HiveDeploy.bat qui copie uniquement les fichiers du répertoire 12, ne nécessitant pas le recyclage de ma pool d'application. L’exécution étant instantanée, ce script est très utile lorsque l'on effectue une modification sur une page .aspx par exemple, on peut la tester immédiatement car l’application n’a pas besoin d'être redémarrée.

HiveDeploy.bat
Ici, on tire le meilleur parti de WSPBuilder car on profite du fait que la structure de répertoires attendue correspond exactement à celle du répertoire 12. Il suffit de copier notre répertoire 12 dans celui de SharePoint.

@echo off
@SET SPDIR="c:\program files\common files\microsoft shared\web server extensions\12"

cls

ECHO.
Echo ================= Copying files to 12 directory ====================
ECHO.
xcopy /e /y /q 12\* %SPDIR%
ECHO.

QuickDeploy.bat
De même,  on copie notre 12 dans le 12 de SharePoint, ensuite on installe chaque assembly dans son répertoire cible. Enfin, on recycle le pool d'application que l'on utilise pour nos tests.

@echo off
@SET SPDIR="c:\program files\common files\microsoft shared\web server extensions\12"
@SET GACUTIL="C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe"

cls

ECHO.
Echo ================= Copying files to 12 directory ====================
ECHO.
xcopy /e /y /q 12\* %SPDIR%

ECHO.
Echo =================== Installing assemblies to GAC ===================
ECHO.
%GACUTIL% /uf "DemoGAC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=53439e9aa159f9fe" /silent
%GACUTIL% -if ..\DemoGAC\bin\debug\DemoGAC.dll
ECHO.

echo ========== Installing assemblies in Web Application's bin ==========
ECHO.
xcopy /e /y /q ..\Demo80\bin\debug\Demo80.dll "C:\Inetpub\wwwroot\wss\VirtualDirectories\80\bin\"
ECHO.

Echo ================== Recycling Application Pools =====================
ECHO.
cscript C:\WINDOWS\System32\iisapp.vbs /a "SharePoint - 80" /r
ECHO.

Ce qui donne a l’écran :

QuickDeploy


CreatePackage.bat
On récupère les assemblii provenant de nos 2 autres projets, puis on exécute WSPBuilder afin que le package .wsp soit généré.

@echo off
@SET WSPBUILDER="M:\Utilitaires\WSPBuilder\WSPBuilder.exe"
cls

ECHO ================== Updating solution directory =====================
ECHO.
REM deleting bin directory to make sure WSPBuilder won't include unnecessary assemblies in the package
rd .\bin /s /q
copy ..\Demo80\bin\release\Demo80.dll .\80\bin\
copy ..\DemoGAC\bin\release\DemoGAC.dll .\GAC\

ECHO.
ECHO ================== Building package with WSPBuilder ===================
%WSPBUILDER% -WSPName DemoWSPBuilder.wsp -DLLReferencePath ..\Lib\
ECHO.


Pour s’assurer que les assemblii soient compilés avant l’appel à CreatePackage.bat, il faut aussi faire attention à ce que le projet de packaging soit "compilé" en dernier en paramétrant le build-order de la solution. Pour ce faire, on déclare une dépendance de DemoWSP sur les 2 autres projets :

BuildOrder1   Dependencies

 

Remarques :
- WSPBuilder génère automatiquement toutes les policies et balises SafeControl nécessaires, un autre avantage de l’outil. Lorsque c’est nécessaire, pendant la phase de développement, on peut donc déployer le package généré pour éviter d’avoir à faire ces modifications à la main dans le fichier web.config.
- Ce modèle de travail peut être étendu aux solutions utilisant le pattern MVP, moyennant quelques modifications des scripts .bat.

SharePoint 2007 : Comment utiliser la page d’attente standard

Parfois lors d’un gros traitement, un retour serveur peut durer plusieurs secondes. Il est alors d’usage d’informer l’utilisateur qu’un traitement est en cours, comme le fait SharePoint pour toutes les opérations longues, telles que la création d’un site par exemple.

L’objet de ce post, c’est que la page utilisée par SharePoint est prévue pour être utilisée dans vos développements WSS ! Son utilisation est d’ailleurs particulièrement simple: on manipulera juste un objet de type SPLongOperation que l’on instancie en passant une instance de la page courante.

Code

Les propriétés LeadingHTML et TrailingHTML permettent de spécifier le texte affiché dans la page d’attente.

Sur l’appel de la méthode Begin(), l’utilisateur sera transféré sur celle-ci jusqu’à l’appel de la méthode End(). Attention donc à appeler End() quoi qu’il arrive sinon l’utilisateur restera coincé sur la page d’attente. End() prend en paramètre l’url vers laquelle l’utilisateur doit être redirigé.

image

Comme d’habitude avec les objets SharePoint, les bonnes pratiques imposent qu'on libère les ressources via la méthode Dispose(), ou en utilisant l’objet dans un bloc using.

SharePoint 2007 : Zones et URL internes

Les URL des liens internes dans SharePoint doivent dépendre la zone du site. Lorsqu' on récupère une URL par code, il faut donc faire faire attention à la zone de l' instance d' SPSite utilisée.

Toutes les URL obtenues via le modèle objet de SharePoint dépendent de cette zone, y compris les valeurs des champs de type URL tels que les liens internes ou les photos des utilisateurs.

image 

Lorsqu' on ne précise pas la zone dans le constructeur de SPSite, la zone par défaut (définie dans l' administration centrale) est utilisée. Sur la capture d'écran, on remarque que l' Extranet est configuré comme zone par défaut.

Pour récupérer des URL dans un contexte Web, on privilégiera donc l' utilisation de l' instance SPContext.Current, qui expose des objets correspondant toujours à la zone de la requête en cours.

Si la récupération de l' URL requiert l' utilisation de SPSecurity.RunWithElevatedPrivileges, on est amené à devoir instancier un SPSite différent de celui exposé par SPContext.Current. Il faut alors utiliser le constructeur disposant du paramètre SPUrlZone pour afficher une URL correcte.

 image

Un tel oubli peut être particulièrement gênant lorsqu' il s' agit d' URL d' images. D' autant que lorsqu' on développe, on n' a pas forcément le réflexe de tester nos pages en zone Extranet.


Classé sous , , ,

SharePoint : Détecter un changement de valeur de propriété Personalizable

Dans le cadre du développement d'une évolution (gestion du VB.NET) pour la CodeTesterWebPart, je me suis rendu compte que le modèle objet de la WebPart ne permet pas de savoir directement, sur le set d'une propriété personalizable, si ce set correspond à une action utilisateur (changement de valeur) ou à l'initialisation du contrôle (affectation de la valeur sauvegardée).

N'ayant pas trouvé de documentation sur le sujet, j'ai remonté les deux callstack :

  • Dans le cadre de l'initialisation du contrôle, la propriété est affectée par le SPWebPartManager sur l'événement PageInitComplete de la page.
  • Dans le cadre d'un changement de valeur de propriété par l'utilisateur, le set de la propriété est appellé depuis le RaisePostBackEvent de la page (après le load donc). D'ailleurs, si nous sommes dans ce cas, il s'agît toujours d'une requête POST.

Dans une requête POST, la méthode CreateChildControls() de la WebPart est appellé juste avant le Load de la page, c'est à dire après que la propriété soit initialisée, mais avant qu'elle puisse être changée.

Partant de cette observation, j'utilise la propriété ChildControlsCreated pour déterminer s'il s'agit d'une initialisation ou d'un changement de valeur :

Language


Classé sous , ,

Sharepoint : La CodeTesterWebPart en pratique

Lorsque l'on développe sous Sharepoint, à chaque fois que l'on modifie son code il faut compiler, packager, déployer, recycler son application pool, et attendre que Sharepoint s'initialise. On peut alors vérifier l'éxécution du code si on a la chance d'avoir un bouton qui le déclenche directement, mais celui-ci peut aussi être éxécuté en fin de workflow ou lors d'évènements plus ou moins évidents à reproduire.

Tester du code dans son contexte d'exécution est donc souvent une tâche longue et fastidieuse pour le développeur Sharepoint.

La CodeTesterWebPart permet la compilation et l'éxécution instantanée de code C#. Elle est disponible depuis quelques jours sur CodePlex : http://www.codeplex.com/CodeTesterWebPart

On dispose d'une boite de texte dans laquelle on saisit le code que l'on souhaite, et d'un bouton "Run that method!" qui permet de l'éxécuter instantanément. On peut modifier la liste des assemblies référencées (en spécifiant leur chemin sur le disque) ainsi que les usings :

ListLists

Le bouton "Save Inputs" permet de sauvegarder les références, usings, et le code grâce au concept de Personnalization.

Si il y a des erreurs de compilation, elles sont affichées :

CompilerResults

La méthode de test dispose de deux arguments permettant de tester du code d'interface graphique : la page courante et un placeholder qui est situé juste en dessous du corps de la webpart. Ici, on joue avec un diagramme de gantt et on injecte du javascript dans la page :

Gantt2

Autre avantage, le code s'exécute avec le contexte courant. On peut donc tester tout ce qui concerne les droits. Par exemple, avec un compte visiteur, si on tente de modifier le titre du site courant avec la CodeTesterWebPart, on est redirigé vers la page Access Denied. On se rend alors compte qu'il faut utiliser  SPSecurity.RunWithElevatedPrivileges, le code suivant fonctionne sans problème :

SPSecurity

On pourrait se dire que les limites sont atteintes dès lors que l'on veut tester du code récursif. Non, c'est possible aussi ! Il suffit de tricher un peu sur le parenthèsage. Après tout, le code est compilé tel qu'il est rendu à l'écran.

Recursive

Mais comment ca marche ?!

Le namespace System.CodeDom contient des classes qui permettent de compiler dynamiquement une assembly à partir de code source sous forme de chaine de caractères. La CodeTesterWebPart compile ainsi une assembly en mémoire, il n'y a pas d'écriture sur le disque. La méthode TestMethod est ensuite appellée par reflection, de manière tout à fait classique. Pour les plus curieux, le code source est disponible sur CodePlex.

Sharepoint : Développez plus vite avec la CodeTesterWebPart

Et si on pouvait vérifier que notre code s'exécute comme prévu avant même de le déployer?

Voici la CodeTesterWebPart :

CodeTesterWebPart

Téléchargement : http://www.codeplex.com/CodeTesterWebPart

Conçue dans ce but, j'espère que cette Web part vous fera gagner du temps lors de vos prochains développements :)

Sharepoint : Le contrôle ScriptLink

Le contrôle ScriptLink de Sharepoint permet d'effectuer l'enregistrement d'un fichier javascript dans une page. Voici les avantages de ce contrôle par rapport au ClientScript.RegisterClientScriptInclude() d'ASP.NET :

  • Gestion de la localisation
  • Gestion du cache
  • Le script est toujours référencé dans le header

Les deux choses importantes à savoir avant de l'utiliser sont que le chemin à spécifier doit être relatif au répertoire LAYOUTS (si utilisation sans localisation), et que si le fichier n'est pas trouvé une erreur sera levée.

Dans le cadre d'une utilisation avec localisation, Sharepoint cherchera la version qui correspond à la langue du site dans LAYOUTS/XXXX, où XXXX est le LCID du site courant (1033 pour l'anglais, 1036 pour le français).

Voyons un exemple d'utilisation avec une web part. Chacun des fichiers .js contient une méthode HelloWorld qui lance une alerte avec un message different. Voici la structure et le code du projet :

SLDemo

Dans ce cas c'est le fichier LAYOUTS/SLDemo/ScriptLinkDemo.js qui est référencé :

Neutral

Maintenant essayons avec nos versions localisées, en changeant juste la valeur de Localizable :

Localizable

Résultat à l'éxécution avec un site en francais (LCID 1036):

French

C'est la version qui correpspond au LCID du site qui est utilisée, on peut le vérifier en examinant le code HTML de la page:

Script2

Mais que se passe-t-il si il n'y a pas de fichier pour ce LCID ? Essayons. J'efface le fichier SLDemo/1036/ScriptLinkDemo.js, un coup de iisreset.exe, et je recharge ma page :

Error

On remarque que ni la version neutre ni la version anglaise n'ont été substituées par Sharepoint, et que le message d'erreur n'indique pas le chemin exact attendu. Attention donc à deployer une version par langue susceptible d'être utilisée.


Classé sous , ,

.NET 3.5 : Les certifications

Ca y est, il est possible de passer certaines des certifications du Framework .NET 3.5 !

Attention, seules les certifications relatives aux 3 briques majeures du Framework 3.0 sont prêtes, à savoir :

Les autres sont pour bientôt :

Pour préparer ces examens, on peut commencer par télécharger le training kit de Microsoft : Visual Studio 2008 and .NET Framework 3.5 Training Kit

Bonnes révisions à tous ;)

Technorati Profile

Classé sous ,

Sharepoint 2007 et Framework .NET 3.5 : Intégration d'AJAX en pratique

J'ai souhaité tester moi-même l'intégration d'AJAX dans Sharepoint. Disposant d'un Visual Studio 2008, j'en ai profité pour vérifier que le SP1 de Sharepoint règle le problème de compatibilité avec l'UpdatePanel d'AJAX.

Pré-requis, donc, un WSS mis à jour avec le Service Pack 1, et le Framework .NET 3.5.

Etape 1 : Mise à jour du Web.Config

AJAX requiert des changements assez lourds dans le Web.config de chaque application dans laquelle on l'utilise. Je me suis souvenu être tombé, il y a quelques temps, sur une feature Sharepoint permettant de mettre à jour le web.config : AJAX.Config, disponible dans le package Sharepoint Features 2007 (qui contient d'ailleurs de petits bijoux). Malheureusement, cette feature ne prend pas en compte les nouveaux numéros de version des assemblies du Framework 3.5. L'activer rend inutilisable l'application web à moins que l'ancienne version AJAX ne soit installée.

Il faut donc (à ce jour) mettre à jour le web.config manuellement, suivant la procédure de Microsoft, sans oublier de remplacer tous les numéros de version par 3.5.0.0. Hormi cela, aucun problème : notre application web Sharepoint est maintenant compatible AJAX !

Etape 2 : Modification de la master page

Pour pouvoir utiliser AJAX dans une page, il faut un et un seul ScriptManager. Il est donc recommandé de l'ajouter dans la master page du site. Sur son blog traitant du sujet, Mike suggère d'éditer manuellement le fichier master via un chemin WEBDAV (\\server\<pathtosite>\_catalogs\masterpage), et de placer la balise ScriptManager juste après la balise SPWebPartManager. Facile :

master

Ca y est, notre site est prêt pour accueillir des contrôles AJAX !

On pourrait aussi éditer le master directement dans le répertoire 12, mais puisqu'il s'agît d'un des fichiers par défaut utilisé par Sharepoint, cette manipulation n'est pas supportée par Microsoft. Le mieux en pratique est donc d'utiliser un master personnalisé.

Développement d'une WebPart AJAX

On notera dans le post de Mike le besoin d'utiliser du code qui enregistre un block de script permettant de patcher le javascript de Sharepoint. Dans une configuration WSS 3.0 SP1 + Framework 3.5, ceci est sensé être inutile. J'ai réalisé une toute petite WebPart utilisant un UpdatePanel pour prouver cette théorie :

WebPartCode

Le tour est joué, ça fonctionne !

WebPartScreenShot

Le test est vraiment basique et je compte bien aller plus loin très prochainement. Cela fera sûrement l'objet d'un autre post.


Classé sous , ,
Plus de Messages Page suivante »

Les 10 derniers blogs postés

- TechDays 2010 Genève : Retrouvez-moi pour une session sur la Haute disponibilité et le ScaleOut avec SQL Server par SQL Server vu par Christian Robert le il y a 13 heures et 38 minutes

- [MIX10] Keynote deuxième journée – Internet Explorer 9, Html5, Visual Studio 2010, OData par Atteint de JavaScriptite Aiguë [Cyril Durand] le 03-17-2010, 19:40

- Certifications beta .NET 4 par Kévin Gosse le 03-17-2010, 19:33

- [Mix 2010] – Microsoft Translator Technology Preview V2 par RedoBlog - The .NET Gentleman !!! le 03-17-2010, 18:53

- Lancement en Preview de Cyclone lors des TechDays 2010! par Blog de Frédéric Queudret le 03-17-2010, 16:30

- [WP7] Je ne veux pas d’un nouvel iPhone par Le blog de FremyCompany le 03-17-2010, 13:11

- [WF4] Pourquoi utiliser le ContentPresenter dans l’ActivityDesigner? par Blog de Jérémy Jeanson le 03-17-2010, 07:54

- [Mix 2010] – Telechargez Internet Explorer 9 en Preview ! par RedoBlog - The .NET Gentleman !!! le 03-17-2010, 00:58

- [MIX 2010] – Keynote Day 2 online : Windows Internet Explorer 9, jQuery, OData et Dallas CTP2 ! par RedoBlog - The .NET Gentleman !!! le 03-17-2010, 00:18

- [Mix 2010] – Retour d’expérience développement Seesmic sur Windows Phone 7 par RedoBlog - The .NET Gentleman !!! le 03-16-2010, 23:44