[SharePoint 2010] Site internet et performances : poids et nombre des ressources

Microsoft SharePoint Server 2010

Un site internet hébergé sur SharePoint 2010, c’est bien. Si il s’affiche vite, c’est mieux!

Introduction

Lorsque l’on travaille sur les performances dans le cadre d’une application web, SharePoint ou non, il y a 3 phases à prendre en compte :

  • Le temps que les pages mettent à être générées côté serveur
  • Le temps mis par le navigateur pour télécharger la page (html) et les ressources qui y sont référencées (css, js, images..)
  • Le temps mis par le navigateur pour afficher la page et exécuter les éventuels scripts d’initialisation

A l’heure où la mamie du cantal découvre les joies du surf sur son Smartphone, le développeur doit s’assurer que son site internet s’affichera avec des performances acceptables malgré d’éventuels problèmes de bande passante.

Nous allons aujourd’hui faire un focus sur l’optimisation des performances d’un site internet SharePoint 2010 vis à vis de la 2ème phase, le téléchargement des ressources. Les 2 facteurs principaux sont le poids, mais aussi et surtout le nombre de fichiers référencés.
Nous allons donc voir comment réduire le poids et le nombre des fichiers ressources référencés dans nos pages.

1. Réduire le poids des ressources

Page et ViewState

Dans la plupart des cas le poids de la page est négligeable comparé au poids des ressources.
Par exemple la page d’accueil du site http://www.ca-ifcam.fr pèse 17Ko, pour un total de 660Ko si on ajoute les images, scripts et autres ressources qu’elle référence.

Attention toutefois au ViewState ASP.NET qui est activé par défaut sur tous les contrôles de la page. Il peut faire grossir considérablement le poids des pages si on n’y prête pas attention.
Sur un site internet, il n’y a en principe pas ou peu de raison de faire des retours serveur (PostBack), et donc pas de raison de laisser le ViewState activé.
Pour désactiver le ViewState sur les contrôles où il n’est pas nécessaire, on utilisera l’attribut EnableViewState.

image

Pour plus d’information sur le ViewState, je vous redirige vers la MSDN : Understanding ASP.NET View State

Compression des ressources CSS et JavaScript

Une optimisation incontournable est la compression des fichiers référencés, en particulier les fichiers CSS et JavaScript.

Dans le cadre du site internet IFCAM, nous avons utilisé la librairie YUI Compressor de Yahoo ou plutôt son portage en .NET que l’on peut télécharger librement sur CodePlex : Yahoo! UI Library: YUI Compressor for .Net.
Cette implémentation propose notamment des tâches MSBuild permettant d’automatiser la compression des fichiers lors des builds.

YUI Compressor réduit le poids des CSS et des fichiers JavaScript en supprimant les espaces, commentaires, en réduisant le nombre de caractère des noms de variables, et en faisant d’autres optimisations issues de l’analyse de chaque fichier.
Le gain est significatif :

image

image

Dans notre solution Visual Studio, tous les fichiers css et js existent en version originale (*.debug.css et *.debug.js) et en version compressée (*.css et *.js). On régénère les versions compressées à partir des versions originales avant chaque compilation en mode release.
Pour travailler confortablement, nous avons développé un contrôle spécifique pour référencer les feuilles de style css. Il référence dynamiquement la version debug ou compressée d’un fichier en fonction de la variable de compilation DEBUG.

Code source du contrôle épuré pour meilleure lisibilité :

image

On le positionne dans la balise head de la master page :

image

Cela permet de travailler normalement durant la phase de développement (fichiers originaux debug.css), et d’être sûr que c’est la version compressée qui sera référencée sur l’environnement de production, puisque nous livrons toujours des packages compilés en mode release..

Pour le référencement des fichiers JavaScript, pas besoin de développement spécifique. Il est possible d’utiliser le contrôle ScriptLink de l’API SharePoint qui fonctionne selon le même principe.
Je vous invite à consulter le post de Wictor Wilen qui détaille bien cette approche : http://www.wictorwilen.se/Post/Minifying-custom-JavaScript-files-in-SharePoint-2010.aspx

2. Réduire le nombre des ressources

D’un point de vue expérience utilisateur, l’optimisation la plus significative est de limiter le nombre de fichiers référencés. Le navigateur fera moins d’allers-retours avec le serveur, et affichera donc la page plus vite. Nous allons voir deux méthodes pour réduire le nombre de fichiers référencés : une qui est valable pour toutes les applications web puisqu’elle concerne les images, et une autre spécifique à SharePoint..

Regroupement des images avec CSS Sprites

Le concept de CSS Sprites consiste à mettre plusieurs images côte à côte dans un seul fichier image. On réutilise alors cette image sur tous les boutons de la page et pour chacun d’entre eux on utilise le positionnement CSS pour afficher la partie de l’image qui lui correspond. On notera que ce concept est déjà utilisé par SharePoint pour regrouper dans une seule image toutes les icônes des boutons du ruban.

Pour l’exemple, voici une image construite en CSS Sprite qui regroupe une vingtaine d’images (cliquez pour agrandir) :

bg-blocks

Et la voici utilisée sur la page d’accueil du site IFCAM :

image

Grâce à ce système, on fait l’économie d’une vingtaine d’allers-retours serveur ce qui permet un affichage bien plus rapide de la page dans le navigateur. Cela n’économise pas de bande passante, mais permet d’éviter au navigateur d’établir une connexion par image, ce qui prendrait un temps significatif et potentiellement plus long que les téléchargements eux-mêmes. On notera d’ailleurs que les navigateurs ne doivent pas établir plus de 2 connexions simultanées avec un même serveur (RFC 2616), ce qui empêche de télécharger toutes les images d’une page en parallèle. Sans CSS sprite, les images doivent donc être téléchargées les unes après les autres ce qui ralentit l’affichage.

Un autre avantage du CSS sprite c’est que si l’image “mouse over” d’un bouton est inclue dans la même image que l’originale, il suffit de jouer sur le positionnement en conservant la même image lors du survol de la souris, ce qui est instantané.

A première vue, cela parait complexe à mettre en œuvre mais en utilisant un bon outil, c’est facile.
On en trouve beaucoup sur internet, mais j’ai une préférence Sprite Me qui permet de générer les images et les css à l’aide d’un bookmarklet.
Je vous invite à essayer la démo sur le site http://spriteme.org, l’essayer c’est l’adopter.

Déréférencement des fichiers spécifiques SharePoint

Voici maintenant une méthode spécifique SharePoint. Par défaut dans SharePoint 2010, un grand nombre de fichiers JavaScript et CSS sont référencés. Ceux-ci n’ont pas tous d’intérêt dans le cadre d’un site internet, comme par exemple ceux qui permettent le fonctionnement du ruban. En effet sur un site internet, on n’affiche pas le ruban. On notera aussi que ces fichiers sont particulièrement volumineux.

Dans le cas du site IFCAM, nous souhaitions que pour les internautes, le ruban ne soient pas affiché. Dans ce cas, nous ne voulions pas non plus référencer les CSS systèmes de SharePoint ni les fichiers JavaScript du ruban.

La solution que nous avons retenu est implémentée en 2 parties.

Premièrement nous avons encapsulé certaines références explicites dans notre contrôle spécifique AuthenticatedUserPlaceHolder dont j’avais parlé dans le billet SharePoint 2010 : Masquer le ruban sur un site internet. Ainsi si l’utilisateur est anonyme, les CSS "système" de SharePoint ne seront pas référencées.

image

Lors de l’affichage de la page d’accueil du site IFCAM en anonyme, cette méthode permet d’économiser le téléchargement de controls.css (10Ko) et de corev4.css (30Ko).

Deuxièmement, nous souhaitions nous débarrasser de certains fichiers JavaScript inutiles pour un site internet tels que cui.js, core.js, et SP.Ribbon.js. Ces fichiers ont la particularité d’être référencés dynamiquement via une technique de lazy loading.
Malheureusement jusqu’à peu, la seule méthode connue pour empêcher leur référencement dans les pages consistait en une méthode peu esthétique et non supportée à base de System.Reflection, Celle-ci est détaillée dans le billet de Chris O’Brien : Eliminating large JS files to optimize SharePoint 2010 internet sites.

Il y a quelques jours, les ingénieurs de l’équipe produit de SharePoint ont révélé une manière supportée de parvenir au même résultat, Il suffit d’utiliser une méthode JavaScript non documentée prévue à cet effet.
Merci à Pierrick pour le lien : Supported way of eliminating (large) JS files for SharePoint 2010
L’astuce consiste à enregistrer cette petite instruction JavaScript en bas de page pour que les fichiers JavaScript en question ne soient pas téléchargés :

<script type='text/javascript'>SP.SOD.set_prefetch(0);</script>

Simple, et tout aussi efficace. En pratique, on l’encapsulera bien sur dans un contrôle serveur pour qu’elle ne soit exécutée que dans les cas où on n’a pas besoin des fichiers JavaScript qu’elle empêche de télécharger.

Ci-dessous les métriques pour la page d’accueil prises à l’instant dans ma machine virtuelle de développement.

Sans l’instruction JavaScript :

image

Avec l’instruction JavaScript:

image

On observe une différence de 15 fichiers, représentant 140Ko.

Conclusion

Nous avons vu dans ce billet comment le développeur peut améliorer les performances d’un site internet SharePoint en réduisant le poids des fichiers référencés ainsi que leur nombre.
Pour des performances optimales, l’administrateur aura aussi son rôle à jouer : n’oubliez pas de configurer le BlobCache et le cache de sortie.


Arnault Nouvel
MVP SharePoint Server

[SharePoint 2010] Site internet et performances : le developer dashboard

sharepoint-server

Dans les billets précédents, nous avons vu comment optimiser les performances d’un environnement SharePoint 2010 qui héberge un site internet grâce au BlobCache et au cache de sortie, . Nous allons voir aujourd’hui comment faire apparaitre le developer dashboard dans le cadre d’un site internet pour diagnostiquer les problèmes de performances liés au code serveur.

Apparu avec SharePoint 2010, le developer dashboard fourni une interface de monitoring des performances directement dans les pages SharePoint. Il est très utile lorsque l’on cherche à optimiser les performances du code serveur de l’application. Une API permet notamment d’y afficher des informations à propos de notre propre code, en particulier la durée d’exécution de portions de code ainsi que des détails sur d’éventuelles exceptions gérées. Je vous invite à consulter l’article de Paul Andrew pour plus de détails sur cette API.

Dans ce billet, nous allons nous intéresser à la manière de le faire apparaitre sur un site internet, dont les particularités sont la connexion anonyme et l’absence de ruban.

Autoriser l’affichage du developer dashboard pour les utilisateurs anonymes

Sur un site internet, l’authentification est anonyme. Par défaut, le developer dashboard (et le bouton OnDemand associé) ne s’affiche que si l’utilisateur courant bénéficie de la permission AddAndCustomizePages, qui n’est pas attribuée aux utilisateurs anonymes. Il est toutefois possible d’afficher le developer dashboard en modifiant le niveau de permission requis.

Voici le script PowerShell que j’utilise :

Add-PSSnapin "Microsoft.SharePoint.Powershell" -ErrorAction SilentlyContinue 

$contentService = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$dds = $contentService.DeveloperDashboardSettings
$dds.DisplayLevel = "OnDemand"
$dds.TraceEnabled = $true;

#pour le rendre actif en mode anonyme
$dds.RequiredPermissions = [Microsoft.SharePoint.SPBasePermissions]::EmptyMask

#pour remettre le niveau de droit par défaut
#$dds.RequiredPermissions = [Microsoft.SharePoint.SPBasePermissions]::AddAndCustomizePages

$dds.Update()

Affichage OnDemand sans bouton

La plupart du temps, et c’est le cas avec le script ci-dessus, je préfère configurer le developer dashboard en mode "OnDemand" qui permet de ne l’afficher qu’en cas de besoin, en appuyant sur un bouton dédié dans le ruban. Mais sur un site internet SharePoint, en général on masque le ruban, et donc le bouton. 

L’astuce pour afficher le developer dashboard lorsque le bouton n’est pas visible, c’est d’ajouter developerdashboard=true dans la query string de l’url.

Par exemple : http://mon_site_internet/Pages/accueil.aspx?developerdashboard=true

image


Arnault Nouvel
MVP SharePoint Server

[SharePoint 2010] Site internet et performances : le cache de sortie

Nous avons vu précédemment comment le BlobCache pouvait nous aider à gérer la mise en cache des fichiers de ressources (images, javascript, css, etc.). Dans ce billet, nous allons discuter de l’utilité du cache de sortie (ou Output Cache en anglais), qui permet de mettre en cache le code HTML rendu par les pages .aspx.

Certains articles sur internet détaillent toutes les facettes de cette fonctionnalité, en particulier celui de Fabrice : SharePoint Output Caching dans un site Intranet. Je ne vais donc parler aujourd’hui que de son utilisation dans le cadre spécifique d’un site internet, tel que mis en place sur le site http://www.ca-ifcam.fr.

Bref rappel de l’objectif de cette fonctionnalité : par exemple si 2 utilisateurs affichent la page d’accueil du site à quelques secondes d’intervalle, le cache de sortie va permettre de renvoyer le même rendu HTML au 2ème utilisateur sans avoir à tout recalculer (menus de navigation, contenu des web parts, etc.). Cela permet de soulager le serveur frontal ainsi que le serveur SQL, et d’obtenir des temps de réponse quasi instantanés sur les pages mises en cache.

Sans cache de sortie :

image

Avec cache de sortie, au 2ème appel :

image

Le cache de sortie se configure par l’administrateur de la collection de sites si le fonctionnalité de site de publication est activée. Actions du site > Paramètres du site > Cache de sortie de la collection de sites.

image

Dans cet écran nous avons la possibilité d’activer le cache de sortie, et de choisir un profil de cache différent pour les utilisateurs anonymes et les utilisateurs authentifiés. Cette différenciation est utile puisque par définition les utilisateurs anonymes voient tous une page de la même manière alors que les utilisateurs authentifiés peuvent avoir un rendu différent selon leurs droits respectifs, et leur appartenance à des audiences, etc. On souhaitera donc gérer le cache d’une manière différente pour les utilisateurs authentifiés, ou pas du tout.

Chaque profil de cache définit si le cache est actif et l’ensemble des paramètres qui permettent de déterminer si une page peut être servie à partir du cache ou non.

Par défaut il en existe 4 :

  • Désactivé
  • Internet public
  • Intranet
  • Extranet

Il est possible de les modifier et d’en créer de nouveaux, puisqu’en en pratique il s’agit d’une liste SharePoint cachée. Pour accéder à cette liste : Actions du site > Paramètres du site > Profils de cache de la collection de sites.

image

Dans le cas d’un site internet, le profil de cache anonyme le plus adapté est "Internet public (purement anonyme)".

image

Le profil "Internet public (purement anonyme)" propose le niveau de cache maximum. Il ne prend pas en compte les différences de droits entre les utilisateurs, ni des éventuelles modifications sur le site. Puisque tous les utilisateurs anonymes doivent voir le même contenu dans les pages, ce profil de cache est parfaitement adapté pour l’authentification anonyme.

On notera que "Variation par paramètre personnalisé" a pour valeur "Browser", ce qui veut dire que si une page a été servie à un visiteur disposant d’un certain navigateur, puis mise en cache, cette version de la page ne sera pas resservie telle-quelle à un autre visiteur si il a un navigateur différent. Pour chaque navigateur différent (ou de version différente), une copie d’une même page sera mise en cache.

Les paramètres intéressants à modifier dans le cadre d’un site internet :

  • Par défaut ce profil de cache a une durée de 180 secondes, il peut être utile d’augmenter cette valeur. On gardera cependant à l’esprit que chaque page mise en cache consomme de la mémoire vive.
  • Certains composants graphiques, notamment les web parts, peuvent dépendre de paramètres dans l’url (query string). C’est le cas par exemple de la web part des résultats de recherche catalogue du site http://www.ca-ifcam.fr. Si vous en disposez sur votre site, il peut être intéressant d’indiquer le nom de ces paramètres dans le champ "Variation par paramètres de chaines de requête" séparés par des point-virgules, ou tout simplement mettre la valeur * pour qu’ils soient tous pris en compte.

Conclusion

Tout comme le BlobCache, le cache de sortie est incontournable pour obtenir de meilleures performances sur un site internet réalisé en SharePoint 2010. Activé par un administrateur de la collection de sites, il est à la fois facile à mettre en place et très efficace : la charge serveur est diminuée et les pages mises en cache sont retournées quasi-instantanément.

Nous verrons dans le prochain billet comment un développeur peut encore améliorer les performances d’un site internet sous SharePoint 2010.


Arnault Nouvel
www.winwise.com

[SharePoint 2010] Site internet et performances : le BlobCache

Un nouveau site internet réalisé en SharePoint 2010, et développé par Winwise, vient d’apparaitre sur la toile : http://www.ca-ifcam.fr.
Pour introduire brièvement ce projet, ce site a pour vocation principale d’exposer un catalogue de formation aux salariés du groupe Crédit Agricole. Les plus curieux trouveront la partie la plus intéressante via la recherche catalogue. Passons maintenant au retour d’expérience !

De bonnes performances sont essentielles au succès d’un site internet. Pour les obtenir, nous verrons dans une série de billets qu’il est possible d’intervenir à plusieurs niveaux. L’administrateur, le développeur, et même les auteurs de contenu ont un rôle à jouer. Commençons par le BlobCache, qui peut être activé par l’administrateur.

Disponible nativement dans SharePoint, le BlobCache est un mécanisme de cache de ressources qui s’avère particulièrement efficace dans le cadre d'un site internet. Il permet de mettre en place à la fois du cache serveur et du cache client. Dans ce billet nous allons voir en quoi consiste le BlobCache, puis comment le configurer.

Le cache serveur

Par défaut (sans BlobCache) lorsqu'un fichier de ressource stocké dans une bibliothèque SharePoint est demandé, le serveur frontal récupère systématiquement le fichier en base de données et le renvoie au client. Prenons par exemple le cas d’un logo affiché sur plusieurs les pages d’un site, ou d’une feuille de style CSS référencée dans toutes les pages. Ces ressources étant demandées très fréquemment et n’étant pas amenées à changer souvent, il est dommage de solliciter le serveur SQL pour les récupérer à chaque fois qu’un utilisateur les demande.

Une fois activé, le BlobCache permet de résoudre ce problème : après avoir récupéré une ressource en base de données, le serveur frontal conserve le fichier sur son disque dur. Ce fichier est ensuite servi aux utilisateurs lors des requêtes suivantes directement depuis le disque dur, sans avoir à refaire un aller-retour avec le serveur SQL. Cela permet de limiter considérablement le nombre de connexions entre les serveurs frontaux et le serveur SQL. En terme de performances, on gagne donc en charge sur le serveur SQL, et en temps de réponse pour récupérer les ressources si elles sont déjà en cache.

Le cache client

L'activation du BlobCache a un 2ème intérêt, moins connu mais tout aussi important en terme de gain de performances puisqu'il permet de limiter les aller-retours entre le navigateur client et le serveur frontal.

Nous allons mettre en évidence le gain de performances avec un de mes outils préférés, HTTP Watch Professionnal. Pour ce faire, nous allons requêter 2 fois de suite une image située dans une bibliothèque SharePoint, et analyser les entêtes HTTP des requêtes et des réponses. Sur chaque capture d’écran on peut voir à gauche la requête, et à droite la réponse.

Sans BlobCache

clip_image001

Lors du premier appel, la réponse indique Cache-Control : private,max-age=0. Cela indique au navigateur qu’il ne peut pas mettre cette image en cache. L’image sera toutefois conservée dans les fichiers internet temporaires.

sans-blob-cache-2

Lors du 2ème appel, le navigateur demande l'image en précisant qu'il en dispose déjà d’une version dans ses fichiers temporaires, en passant la date de celle-ci (champ if-modified-since) dans le header de la requête HTTP. Le serveur constatant que l'image n’a pas été modifiée depuis cette date, il renvoie une réponse 304 qui indique au navigateur que l’image n’a pas besoin d’être re téléchargée. L’image stockée dans les fichiers temporaires va donc être réutilisée.

L’image n’est pas re-téléchargée lors du 2ème appel, mais il y a tout de même eu un aller-retour serveur qui a un cout en terme de performances.

Avec BlobCache

clip_image003

Lors du premier appel, la réponse indique Cache-Control : public,max-age=86400. Cela indique au navigateur qu’il peut conserver la ressource en cache et la réutiliser pendant 86400 secondes (24 heures).

clip_image004

Lors du 2ème appel, aucune requête n'est effectuée vers le serveur. En effet puisqu’elle a été mise en cache il y a moins de 24 heures, le navigateur sait qu'il peut réutiliser l'image sans se poser de question, et surtout sans en poser au serveur Sourire

Le BlobCache nous permet donc d’économiser un aller-retour serveur à chaque fois qu’une ressource est redemandée !

Voyons maintenant comment l’activer. 

Activation du BlobCache

Le BlobCache peut être activé par un administrateur de la ferme en modifiant le web.config de l'application sur chaque serveur frontal de la ferme.

Il se configure au niveau de l'élément <BlobCache /> qui est présent par défaut :

<BlobCache location="C:\BlobCache\14" path="\.(gif|jpg|jpeg|jpe|jfif|bmp|dib|tif|tiff|ico|png|wdp|hdp|css|js|asf|avi|flv|m4v|mov|mp3|mp4|mpeg|mpg|rm|rmvb|wma|wmv)$" maxSize="10" enabled="false" />

Les attributs sont les suivants :

  • L'attribut Location permet de définir le répertoire dans lequel seront conservés les fichiers sur le serveur.
  • L'attribut maxSize permet de définir, en Go, l'espace disque que peut occuper le BlobCache.
  • L'attribut path permet de définir les extensions des fichiers que doit prendre en charge le BlobCache. On peut ici ajouter d’autres extensions.
  • L'attribut enabled permet d'activer ou de désactiver le BlobCache.
  • Enfin, on peut ajouter un attribut max-age qui n'est pas présent par défaut. On y donne une valeur en seconde de la durée de mise en cache.

Pour activer le BlobCache sur une application web, il faut donc de modifier la valeur de l'attribut enabled dans les web.config de chaque frontal de la ferme.

Exemple :

<BlobCache location="C:\BlobCache\14" path="\.(gif|jpg|jpeg|jpe|jfif|bmp|dib|tif|tiff|ico|png|wdp|hdp|css|js|asf|avi|flv|m4v|mov|mp3|mp4|mpeg|mpg|rm|rmvb|wma|wmv)$" maxSize="10" enabled="true" max-age="592200" />

Conclusion

Dans ce billet nous avons vu comment améliorer les performances d'une application SharePoint en mettant en place le BlobCache.

Celui-ci permet de réduire la charge sur le serveur SQL et sur le serveur Frontal, tout en limitant le nombre de requête effectuée par le navigateur, améliorant donc l'expérience utilisateur. Dans le cadre d'un site internet hébergé sous SharePoint 2010, le BlobCache est incontournable.

Nous verrons dans le prochain billet comment améliorer encore les performances grâce au cache de sortie.

Arnault Nouvel – Winwise

SharePoint 2010 : Performances d’un serveur SharePoint sans accès internet

Sur un serveur SharePoint, l’absence d’accès à internet peut avoir un lourd impact sur les performances.  En effet pour diverses raisons, ASP.NET et SharePoint vérifient la validité de certaines informations et certificats sur les serveurs de Microsoft. Cela se traduit par des tentatives de connexion à crl.microsoft.com (modes classic et claims) et www.download.windowsupdate.com (claims uniquement) pendant l’exécution de l’application.

Après avoir mis en évidence la problématique, nous allons voir comment désactiver les mécanismes qui provoquent des connexions vers internet. Nous retrouveront alors des performances optimales.

Mise en évidence du problème

Les tests qui vont suivre ont été réalisés sur une machine virtuelle de développement Windows 2008 R2 embarquant à la fois un Active Directory, un serveur SQL, et un SharePoint Server 2010. Un IISRESET est effectué avant chaque mesure, une mesure correspondant au temps d’affichage de la page d’accueil d’un site d’équipe.  Pour bien mettre en évidence les problématiques liées au mode claims, chaque test est effectué dans les 2 modes. Les mesures des temps de réponses ont été prises avec HttpWatch Professional.

Afin d’établir un référentiel, je commence par prendre des mesures en conservant un accès internet sur le serveur :

image
Web App en mode classic avec accès internet : 10.6 secondes

image
Web App en mode claims avec accès internet : 15.2 secondes

Après avoir coupé l’accès internet, je ré effectue le même test :

image
Web App en mode classic sans accès internet : 42.3 secondes

image
Web App en mode claims sans accès internet : 57.8 secondes

Le temps de chargement est donc multiplié environ par  4. Edifiant n’est-ce pas ?

Ces latences sont dues au fait que le serveur tente de se connecter à divers services sur internet. En l’absence d’accès à internet, ces tentatives de connexions génèrent des timeout qui ralentissent l’exécution des applications.

Dans un scénario de développement, la baisse de productivité est significative puisque le développeur attend inutilement 30 à 45 secondes à chaque fois qu’il appuie sur F5 pour déployer de son projet.

Dans un scénario de production, on ne recycle pas les application pool aussi fréquemment, le problème parait donc moins gênant. Toutefois en cas d’authentification par formulaire (mode claims), une demande d’authentification peut prendre plusieurs secondes. Sur un portail extranet que j’ai étudié récemment, un utilisateur attendait systématiquement 15 secondes après avoir validé la saisie de son login et de son mot de passe, sans raison apparente, avant d’être authentifié par le serveur.

Nous allons voir que les connexions initiées par un serveur SharePoint ont 2 origines : la vérification des signatures des assemblii (en modes classic et claims), et la récupération d’une mise à jour des certificats racines (en mode claims uniquement).

Vérification des signatures des assemblii (modes classic et claims)

La vérification des signatures d’assemblii concerne Code Access Security (CAS) et est propre aux applications ASP.NET. Il s’agit d’un comportement bien connu qui existe aussi sur les environnements SharePoint 2007. Lors du chargement d’assemblii signées (celles du Framework.NET par exemple), des requêtes vers crl.microsoft.com sont faites par IIS pour en vérifier les signatures.

En cas d’absence d’accès internet, il est légitime de désactiver cette vérification en effectuant une modification dans le fichier machine.config situé dans le répertoire C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG. Une fois le fichier ouvert, localiser le noeud <runtime /> et le modifier comme ceci :

<runtime>

   <generatePublisherEvidence enabled="false" />

</runtime>

Après enregistrement, reprenons les mesures :

image
Web app en mode classic : 9.4 sec

image
Web app en mode claims : 25.4 sec

On remarque qu’en mode classic, on a d’encore meilleures performances qu’avec un accès internet. C’est logique puisque le mécanisme de vérification des signatures d’assemblii est entièrement désactivé. On économise un peu de temps CPU et surtout des connexions réseau.

Mais en mode claims, il y a toujours une latence qui semble injustifiée.

Mise à jour des certificats racines (mode claims)

Le Developer Dashboard permet d’identifier l’origine du problème. Pour la mesure prise précédemment (25.4s), il affiche ceci :

image

On constate que les 11.5 secondes "injustifiées" sont consommées au niveau de la méthode SPCertificateValidator.Validate(). Le rôle de cette méthode est de vérifier la validité du certificat utilisé pour chiffrer les communications avec le Security Token Service (STS). 

On trouve le certificat du STS dans le magasin "Local Computer\SharePoint".

image

On remarque que ce certificat est généré par une autorité de certification "SharePoint Root Authority". Malheureusement, cette autorité de certification ne fait pas partie des certificats racines trustés nativement par Windows (les Trusted Root Certificates). SharePoint étant une application, il serait injustifié qu’il en fasse partie.

image

Puisqu’il ne fait pas partie des Trusted Root Certificates, Windows cherche à récupérer une liste à jour des certificats racines afin de vérifier la validité du certificat avec des informations à jour. 
Analysé avec Network Monitor, une tentative de connexion vers http://download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/authrootstl.cab est effectuée pour essayer de récupérer cette mise à jour.

En l’absence d’accès à internet sur le serveur, c’est ici qu’apparait le timeout.

Il est toutefois possible de désactiver cette mise à jour automatique, en suivant cette procédure :

  • Sur le serveur, executer gpedit.msc
  • Aller à Computer Configuration –> Windows Settings –> Security Settings –> Public Key Policies
  • Afficher les propriétés de "Certificate Path Validation Settings"
  • Dans l’onglet "Network Retrieval", cocher "Define this policy" et décocher "Automatically update certificates in the Microsoft Root Certificate Program"
  • Valider, puis exécuter "gpupdate /force" en ligne de commande pour appliquer les modifications

image

Après avoir effectué cette modification, on retrouve des mesures optimales, meilleures que celle prises initialement avec un accès internet.

image
Web app en mode claims : 13.9 sec

On notera aussi que le Developer Dashboard ne signale plus de latence au niveau de la méthode de vérification du certificat :

image

A ce stade, le serveur n’effectue plus de connexion vers internet en rapport avec l’exécution de SharePoint.


Arnault Nouvel
www.winwise.com

SharePoint 2010 : Masquer le ruban sur un site internet

sharepoint-server

Lorsque l’on utilise SharePoint 2010 pour héberger un site internet, une des premières tâches est l’intégration de la charte graphique. Dans la plupart des cas, le ruban ne devra pas apparaitre pour les internautes. Voyons une implémentation possible pour le masquer proprement.

Une particularité d’un site SharePoint par défaut est qu’en cas de scroll vertical, ce n’est pas la scrollbar du navigateur qui apparait, mais celle d’une div qui contient toute la page sauf le ruban. Cela permet notamment de conserver les boutons d’édition de texte même lorsque l’on édite le bas de la page. Cette zone scrollable est redimensionnée dynamiquement par script en fonction de la hauteur du ruban qui peut varier selon l’onglet sélectionné, et de la hauteur du navigateur qui peut être changée à la volée par l’utilisateur.  Ce script qui contrôle la zone scrollable en temps réel causes des problèmes sur certains navigateurs, en particulier Safari et ses dérivés mobiles.

image

On trouve sur internet plusieurs approches pour masquer le ruban. Nous allons découvrir aujourd’hui celle implémentée il y a un an déjà sur le site www.oddo.fr, et que je réutilise aujourd’hui dans le cadre d’un autre site internet.

L’objectif

Afin de bien comprendre le principe, sachez que l’application web qui héberge le site est accessible en mode authentifié pour les auteurs et en mode anonyme pour les internautes.

Concernant la solution envisagée, l’idée est que si l’utilisateur est anonyme, il s’agit d’un internaute et le ruban ne doit donc pas apparaitre. Dans ce cas, il n’y a pas de raison d’utiliser une div scrollable au lieu de la scrollbar de la fenêtre du navigateur.

Afin d’en simplifier l’implémentation, j’ai redéfini mon objectif comme ceci :

  • Par défaut (et donc pour les utilisateurs anonymes) : masquer le ruban, activer la scrollbar du navigateur, désactiver la scrollbar de la div principale
  • Si l’utilisateur est authentifié (auteur du site) : afficher le ruban, désactiver la scrollbar du navigateur, activer la scrollbar de la div principale

Les 3 composantes techniques de l’implémentation sont :

  • 1 contrôle dont le contenu ne s’affiche que si l’utilisateur connecté est authentifié. Celui-ci encapsulera le contrôle serveur du ruban et une surcharge CSS.
  • 1 règle CSS par défaut qui annule la div scrollable, et active les scrollbars du navigateur
  • 1 surcharge CSS qui réactive la zone scrollable uniquement si le ruban est affiché

Le contrôle graphique AuthenticatedUserPlaceHolder

Dans le projet, on crée le contrôle graphique suivant :

public class AuthenticatedUserPlaceHolder : PlaceHolder

{

    protected override void OnInit(EventArgs e)

    {

        //On n'affiche ce contrôle (et donc son contenu) que si l'utilisateur est authentifié

        this.Visible = HttpContext.Current.User.Identity.IsAuthenticated;

    }

}

 

Update : Selon le besoin initial, utiliser les contrôles SPSecurityTrimmedControl ou LoginView permettrait d’obtenir un résultat équivalent sans avoir à développer de contrôle supplémentaire, voir commentaires en bas du post.

Règles CSS par défaut

Dans la balise HEAD de la master page, ou dans la feuille de style principale du projet (préférable), on active la scrollbar du navigateur. Pour simplifier la compréhension, j’inclus ici mes règles CSS directement dans la balise HEAD de la master page :

 

<head runat="server">

   

    …

 

    <style>

        /* active le scroll au niveau de la fenêtre du navigateur */

        body

        {

            height: 100%;

            overflow: auto;

            width: 100%;

        }

 

        /* supprime les barres de scroll au niveau de la zone scrollable de SharePoint */

        body #s4-workspace{

               overflow:visible;

               overflow-x:visible;

               overflow-y:visible;

        }

    </style>

</head>

Attention : sur la balise <body>, un attribut scroll="no" peut empêcher la scrollbar du navigateur d’être affichée par notre règle CSS. S’il est présent, il est nécessaire de le supprimer.

image

Si on suit ce tutorial avec la master page V4.master, on supprimera aussi l’attribut class="v4master" qui surchargerait nos règles CSS avec des clauses !important. Sur une master page custom, en principe cette problématique disparait.

Affichage conditionnel du ruban et des règles CSS associées

Dans la master page, localiser la div ayant pour identifiant s4-ribbonrow, et l’encapsuler avec notre contrôle AuthenticatedUserPlaceHolder. On ajoutera aussi des règles CSS pour activer la zone scrollable (s4-workspace).

Voici le résultat attendu :

<Winwise:AuthenticatedUserPlaceHolder runat="server" >

   

    <style>

              /* supprime le scroll du navigateur */

              body{

                    overflow:hidden;

             }

            

              /* réactive le scroll de la zone scrollable de SharePoint */

             body #s4-workspace{

                    overflow-x:auto;

                    overflow-y:scroll;

             }

    </style>

   

    <div id="s4-ribbonrow" class="s4-pr s4-ribbonrowhidetitle">

        <div id="s4-ribboncont">

            <!-- ribbon starts here -->

            ...

            

        </div>

    </div>

</Winwise:AuthenticatedUserPlaceHolder>

Et hop, on obtient un site web internet sans ruban, avec un scrolling fonctionnel, en conservant une expérience utilisateur normale (avec ruban) lorsqu’un utilisateur est authentifié.

Happy Branding !

Arnault Nouvel
www.winwise.com

SharePoint : Gestion des paramètres applicatifs dans le Property Bag

sharepoint-server

Dans la plupart des développements SharePoint, il est nécessaire de stocker des paramètres applicatifs (chemin d’un répertoire temporaire, url d’un web service, clé de série d’un composant tiers, etc.). Le reflexe habituel des diverses équipes que j’ai pu côtoyer est de créer de nouvelles entrées dans la section AppSettings du Web.Config. Je préfère en général utiliser une autre approche que nous allons évoquer aujourd’hui, le property bag.

Tout d’abord, pourquoi faudrait-il éviter de stocker un paramètre dans le Web.Config ?

  • Déployer le paramètre provoque un redémarrage de l’application web
  • Modifier sa valeur provoque aussi un redémarrage de l’application web
  • La valeur est inaccessible hors du contexte la web application : la central admin, aux SPJobDefinition, scripts PowerShell, etc. ne pourraient pas y accéder de manière directe 
  • Le paramétrage à répliquer sur chaque frontal de la ferme (risque d’erreur de saisie)
  • Problématiques liées aux backup/restore

Dans SharePoint, la quasi totalité des paramètres se configurent à l’aide l’interface web (centrale admin, ou paramètres du site pour les fonctionnels) ou de lignes de commandes (stsadm ou PowerShell). Il parait donc naturel de faire de même avec les développements spécifiques. Je stocke donc toujours mes paramètres applicatifs dans le property bag.

Les avantages sont multiples :

  • Les paramètres peuvent être associés à un périmètre précis : Application web, mais aussi ferme, collection de sites, site, liste et élément de liste.
  • Ils peuvent être modifiés sans nécessiter de redémarrage de l'application web
  • Ils sont persisté dans la base de données SharePoint, et sont donc backupés avec
  • Ils sont administrables par interface graphique (dev) ou par ligne de commande PowerShell
  • Les modifications n’ont pas à être faites sur chaque serveur

Administration par ligne de commande PowerShell

Afin d’éviter le développement d’une page de configuration pour ces paramètres, on aurait pu proposer une administration avec PowerShell. Voici un exemple qui récupère et redéfinit un paramètre :

image


 

Administration avec une interface générique

Le projet communautaire SharePoint Property Bag Settings permet l’administration de tous les property bags de la ferme depuis l’administration centrale.

image

L’interface proposée est générique, efficace, mais réservée aux administrateurs de ferme.

Téléchargement :

 

Administration personnalisée avec une interface spécifique

Pour une interface administration personnalisée, on pourra développer une CustomAction et une page applicative, ou tout simplement une web part. C’est l’approche que j’utilise le plus souvent. En voici un exemple.

Déclaration de la custom action :

image

On obtient alors une nouvelle dans les paramètres du site :

image

Page applicative cible :

image

Pour la partie graphique de la page, on peut s’inspirer des pages présentes nativement dans 14\TEMPLATE\LAYOUTS, comme SiteNavigationSettings.aspx. Cela permet de conserver le look & feel de SharePoint.

Enregistrement des données dans le property bag :

protected void Validate_Click(object sender, EventArgs e)

{

    if (!Page.IsValid)

        return;

 

    //Récupération du property bag de la collection de sites

    SPPropertyBag properties = Site.RootWeb.Properties;

 

    //Enregistrement des valeurs

    properties["Account_GoogleAnalytics"] = txtGoogleAnalytics.Text;

    properties["Account_ShareThis"] = txtShareThis.Text;

    properties["Search_Site_Url"] = txtSiteSearch.Text;

    properties["Search_Catalog_Url"] = txtCatalogSearch.Text;

    properties["WebService_Catalog_Url"] = txtTrainingWebServiceUrl.Text;

 

    //Persiste les modifications dans la base de données

    properties.Update();

 

    //Redirection vers l'URL source

    SPUtility.Redirect(Web.Url, SPRedirectFlags.UseSource, HttpContext.Current);

}

Récupération de la valeur d’un paramètre :

//Récupération de l'adresse du web service

String catalogServiceUrl = site.RootWeb.Properties["WebService_Catalog_Url"];

 

 

Autres alternatives

Nous avons parlé du web.config, du property bag, mais il existe 2 autres options intéressantes pour le stockage de paramètres : le Hierarchical Object Store, et les listes SharePoint.

Vous trouverez ici un comparatif de ces 4 techniques  : http://msdn.microsoft.com/en-us/library/ff649798.aspx

 

Arnault Nouvel
Winwise


Classé sous ,

SharePoint : Développer des colonnes calculées

Contrairement à ce que l’on pourrait penser, il y a 2 types de colonnes calculées dans SharePoint :

  • les <Field Type="Calculated" /> que l’on peut créer avec l’interface habituelle, dans lesquelles on manipule des formules,
  • et les <Field Type="Computed" /> qu’on ne peut créer que via une définition CAML ou par modèle objet.

Les 2 types permettent de définir des colonnes en lecture seule dont la valeur dépend d’autres champs de l’élément. Le premier permet notamment de faire de très jolies choses lorsqu’il est couplé à du code JavaScript, comme expliqué ici : Using calculated columns to write HTML. Aujourd’hui, nous allons parler du 2ème type, qui m’a permis de répondre à 2 besoins à la fois chez l’un de mes clients. Dans son extranet SharePoint 2007, orienté publication de contenu, celui-ci utilise beaucoup de web parts associées à des bibliothèques. Celles-ci étant plus simples à mettre en place que des web parts requêtes de contenu, c’est elles que mon client utilise pour afficher le contenu de ses bibliothèques à ses utilisateurs.

Son premier besoin est que si le titre d’un document est renseigné, ce soit le titre qui soit affiché au lieu de son nom. Il est très facile de répondre à ce besoin via une web part requête de contenu, mais rien ne permet nativement de le faire dans une web part de bibliothèque.

D’autre part, les utilisateurs se plaignent que, lorsqu’ils cliquent sur un document office, l’application leur demande de se ré authentifier. Cela vient du fait que, dans les web parts de bibliothèques, les liens vers les documents indiquent aux applications office de s’ouvrir et de travailler avec le document de manière distante. L’application Office, qui par définition est executée dans un processus différent, doit donc s’authentifier indépendamment du navigateur.
A contrario, sur un site web classique, un lien vers un document retourne simplement le dit document afin qu’il soit téléchargé par l’utilisateur et que celui-ci travaille avec en local. L’extranet de mon client étant orienté publication de contenu, il souhaite que les documents soient téléchargés et non ouverts de manière distante. Là encore, c’est plutôt simple à mettre en place avec une web part requête de contenu, mais ce n’est pas prévu en standard dans une web part de bibliothèque.

Avec le comportement par défaut, on obtient ceci lorsque l’on clique sur le lien du document (colonne “Nom”) :

f1

Quelque-soit le mode choisit, Word s’ouvre et essaye d’ouvrir le document situé sur le serveur, provoquant une demande d’authentification :

f2

Ce comportement n’est pas souhaitable dans le cadre d’un site de publication. Ce qu’on veut, c’est que le document soit tout simplement téléchargé en local.

Pour proposer un lien de téléchargement de document, on peut utiliser la “page” /_layouts/download.aspx, qui prend en query string un argument SourceUrl permettant de spécifier l’url d’un fichier que l’on souhaite télécharger. Nous allons voir comment proposer un lien dynamique vers cette “page” dans une colonne de bibliothèque. Exemple : http://sncfc.nwtraders.com/_layouts/download.aspx?SourceUrl=/monsite/documents/document1.docx.

Les colonnes calculées (Type=”Computed”) permettent de définir un rendu HTML à partir de patterns XML. Le principe est approximativement le même que pour les transformations XSLT, mais le langage est différent. Ici pas de classe à développer, juste une définition de colonne à écrire en CAML.

Voici la définition de colonne répondant au besoin énoncé ci-dessus :

<Field ID="{19B08457-9C22-4d54-BC74-BC321E1704EC}" Type="Computed" Name="DownloadLinkWithTitleOrName" StaticName="DownloadlinkWithTitleOrName" DisplayName="Document" Hidden="FALSE" CanToggleHidden="FALSE" Sortable="TRUE" Filterable="FALSE" AuthoringInfo="(Lien de téléchargement avec affichage du titre ou du nom)" SourceID="http://schemas.microsoft.com/sharepoint/v3" FromBaseType="TRUE" ReadOnly="TRUE" >

       <FieldRefs>

             <!-- Colonnes utilisées par la colonne calculée -->

             <FieldRef Name="Title"/>

             <FieldRef Name="FileRef"/>

       </FieldRefs>

       <DisplayPattern>

             <!-- Le lien pointe vers /_layouts/download.aspx qui renvoie le fichier dont l'url est en paramètre -->

             <HTML><![CDATA[<a href="http://blogs.developpeur.org/_layouts/download.aspx?sourceUrl=]]></HTML>

             <!-- Url du fichier encodée -->

             <LookupColumn Name="FileRef" URLEncodeAsURL="TRUE"/>

             <HTML><![CDATA[">]]></HTML>

             <!-- Définition d’une variable ItemTitle -->

             <SetVar Name="ItemTitle">

                    <LookupColumn Name="Title" StripWS="TRUE" HTMLEncode="TRUE" />

             </SetVar>

             <Switch StripWS="TRUE">

                    <Expr>

                           <GetVar Name="ItemTitle" StripWS="TRUE" />

                    </Expr>

                    <!-- Si le titre est vide, j'affiche le nom du document -->

                    <Case Value="">

                           <UrlBaseName HTMLEncode="TRUE">

                                  <LookupColumn Name="FileRef"/>

                           </UrlBaseName>

                    </Case>

                    <!-- Si le titre est rempli, j'affiche le titre du document -->

                    <Default>

                           <GetVar Name="ItemTitle" StripWS="TRUE" />

                    </Default>

             </Switch>

             <HTML><![CDATA[</a>]]></HTML>

       </DisplayPattern>

</Field>

On notera qu’il est nécessaire de déclarer les colonnes dont on utilise la valeur, dans l’élémént FieldRefs. Si ce n’est pas fait, à l’éxecution, les colonnes apparaitront comme vides.

On notera aussi l’utilisation de l’instruction Switch qui est résolue pour chaque élément du jeu de résultat, contrairement à FieldSwitch qui n’est résolue que pour le premier résultat et dont la valeur est réutilisée pour tous les éléments du jeu de résultat. Je précise cela car la plupart des exemples trouvés sur internet utilisent FieldSwitch.

Une fois cette colonne associée (par code avec la méthode list.Fields.AddFieldAsXml(xml) ou via une définition de liste custom, on peut l’ajouter à nos vues :

image

Et voici le rendu. Notez que, contrairement à la colonne “Nom”, le lien de la colonne “Document” propose le document au téléchargement :

image

Vous trouverez ici l’ensemble des balises qu’il est possible d’utiliser dans les patterns de rendu : http://msdn.microsoft.com/en-us/library/ms439798.aspx

Notez qu’il existe certaines limitations avec cette méthode lorsqu’elle est utilisée sur des types de contenu, décrites dans ce billet au titre un peu exagéré : Do not use SharePoint Computed fields 

Arnault Nouvel
Winwise


Classé sous ,

SharePoint 2010 : Développer un WebTemplate

SharePoint 2010 propose de nouvelles manières de développer un modèle de site personnalisé :

Développement d’une définition de site

Pas de changement majeur par rapport à la version 2007, une définition de site impose toujours de déployer un fichier webtemp.xml en plus du fichier onet.xml. Pour SharePoint 2010, Visual Studio 2010 propose un type et un élément de projet spécifique pour créer une définition de site.

Génération à la souris d’un modèle de site

Je parle ici du modèle de site généré automatiquement lorsque l’on utilise la fonctionnalité “Enregistrer en tant que modèle de site” de la page des paramètres d’un site.

Avec SharePoint 2010, cela génère un package .wsp de type solution sandbox (en 2007, cela générait un .stp qui avait certaines limitations).

On peut éventuellement le réutiliser dans une autre ferme et/ou l’importer dans Visual Studio 2010 pour y effectuer des modifications. Malheureusement en l’important dans Visual Studio 2010, on constatera qu’un projet initié sur cette base serait difficilement maintenable car tous les éléments de base y sont redéfinis. On notera toutefois que le modèle de site généré est un WebTemplate.

Développement d’un WebTemplate

Nouveauté SharePoint 2010, l’élément de feature WebTemplate permet de créer un modèle de site en “héritant” d’une définition de site. Cet élément peut être de scope Farm ou Site. En cas de scope Site, il peut être déployé dans une solution sandbox.

L’héritage en question n’est que déclaratif : on devra fournir un onet.xml qui sera utilisé par SharePoint au moment de la création d’un site. Suite à sa création, l’onet.xml sera “oublié” et le site sera considéré comme ayant été créé avec la définition de site “héritée”.

A mon sens, l’intérêt majeur de cette nouveauté est la facilité qu’elle apportera lors de la migration vers la prochaine version de SharePoint. Chaque site existant créé via un WebTemplate bénéficiera des traitements de migration prévus par l’équipe produit pour la définition de site dont il hérite.

Pour développer un WebTemplate, l’approche consiste donc à fournir un onet.xml minimal dans lequel on référence des features de scope web. Passer par des features plutôt que par des éléments xml dans l’onet facilite la maintenance et garantie une meilleure portabilité en cas de migration puisque migrer des features sera en principe plus aisé que de migrer une définition de site.

On regrettera juste que Visual Studio 2010 n’en propose pas la création d’une manière automatique, contrairement aux définitions de sites.

 

Voici un récapitulatif des avantages et inconvénients des 3 méthodes :

 

Avantages

Inconvénients

Définition de site

  • Modèle de projet dans Visual Studio 2010
  • Migration manuelle

Modèle de site

  • Création par un utilisateur avancé
  • Migration automatique
  • Sandbox Solution
  • Maintenance difficile

WebTemplate

  • Migration automatique
  • Maintenance facile
  • Sandbox ou Farm Solution
  • Déployé en feature (donc activable/désactivable)
  • Limitation (contournable, voir plus bas) sur l’activation des features de collection de sites référencées dans la balise <SiteFeatures> de l’onet.xml

 

Voyons maintenant comment développer un modèle de site avec un WebTemplate.

Développement d’un WebTemplate

Dans Visual Studio 2010, créer un projet SharePoint vide (ou charger un projet SharePoint existant) puis y ajouter un “Empty SharePoint Item” nommé WebTemplate_ClientMeetings.

Dans le fichier elements.xml généré, ajouter la définition suivante :

<?xml version="1.0" encoding="utf-8"?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <WebTemplate Name="WebTemplate_ClientMeetings"

               BaseConfigurationID="1"

               BaseTemplateName="STS"

               BaseTemplateID="1"

               Title="Rendez-vous clients"

               Description="Site de gestion de rendez-vous clients"

               DisplayCategory="Demo"

               Locale="1036"

               />

</Elements>

 

Cette définition indique que l’on crée un modèle de site “Rendez-vous clients” qui “hérite” du modèle de site “Site vierge” (STS#1).

Attention, l’attribut Name doit correspondre au nom du répertoire dans la structure du projet, car il s’agit du nom du répertoire dans lequel SharePoint s’attendra à trouver le fichier onet.xml.

Copier maintenant le fichier …14\TEMPLATE\SiteTemplates\STS\XML\ONET.XML dans le même répertoire.

Sélectionner ensuite le fichier onet.xml dans la structure du projet et indiquer le mode de déploiement “ElementFile”.

image

On peut maintenant faire le ménage dans notre onet.xml afin de ne garder que ce qui nous intéresse, et ajouter les features que l’on souhaite activer. Dans l’exemple, WebTemplate a un attribut BaseConfigurationID="1", on peut donc ne conserver que la configuration ayant l’attribut ID="1".

Voici contenu de mon fichier onet.xml :

<?xml version="1.0" encoding="utf-8"?>

<Project Title="$Resources:onet_TeamWebSite;" Revision="2" ListDir="$Resources:core,lists_Folder;" xmlns:ows="Microsoft SharePoint" UIVersion="4">

 

  <Configurations>

 

    <Configuration ID="1" Name="Blank" MasterUrl="_catalogs/masterpage/v4.master">

      <SiteFeatures>

        <!-- BasicWebParts Feature -->

        <Feature ID="00BFEA71-1C5E-4A24-B310-BA51C3EB7A57" />

        <!-- Three-state Workflow Feature -->

        <Feature ID="FDE5D850-671E-4143-950A-87B473922DC7" />

      </SiteFeatures>

      <WebFeatures>

        <!-- TeamCollab Feature -->

        <Feature ID="00BFEA71-4EA5-48D4-A4AD-7EA5C011ABE5" />

        <!-- MobilityRedirect -->

        <Feature ID="F41CC668-37E5-4743-B4A8-74D1DB3FD8A4" />

 

        <!-- WikiPageHomePage Feature -->

        <Feature ID="00BFEA71-D8FE-4FEC-8DAD-01C19A6E4053" />

        <!-- Apply_MasterPage -->

        <Feature ID="3805d5ae-b975-4652-a644-0f0578a25e1b" />

      </WebFeatures>

    </Configuration>

 

  </Configurations>

 

</Project>

 

Dans cet exemple sont référencées les mêmes features que dans la définition de site parente, plus la feature des pages wiki et une feature custom permettant d’appliquer une master page spécifique.

 

Une fois déployé, un nouvel modèle de site devrait alors apparaitre dans l’écran de création de site :

image

 

Une limitation importante à connaitre

Mon projet exemple est composé de 3 features :

  • Farm_WebTemplate (scope Farm) : la feature qui contient mon élément WebTemplate
  • Site_MasterPage (scope Site) : via un module, elle provisionne la master page personnalisée dans la galerie des master pages de la collection de sites
  • Web_ApplyMasterPage (scope Web) : par code, elle applique la master page personnalisée au site courant

La limitation est la suivante : lorsque l’on crée un site en se basant sur un modèle de site WebTemplate, les features de niveaux collection de sites ne sont pas activées automatiquement. Si dans <SiteFeatures> on en référence une qui n’est pas activée, on aura le message d’erreur suivant lors de la création du site :

image

Pour contourner ce problème, une solution consiste à activer par code la feature de scope Site dans le receiver de la feature Web_ApplyMasterPage, et de ne référencer que la feature de scope Web dans l’onet.xml.

Ci-dessous le code exécuté à l’activation de la feature Web_ApplyMasterPage, qui se charge de l’activation de Site_MasterPage :

image 

Pour plus d’informations sur l’élément WebTemplate, je vous invite à consulter l’article de Vesa Juvonen : SharePoint 2010 and web templates

Arnault Nouvel
Winwise

SharePoint Saturday : Présentation de Winwise.SPMailing

Logo_Club_SharePoint

Le samedi 6 novembre 2010 aura lieu le premier "SharePoint Saturday" organisé par le club SharePoint. Cet évènement, en libre accès, proposera tout au long de la journée des sessions techniques autour de SharePoint. De 45 minutes chacune, elles se dérouleront en ligne via live meeting.

J'ai publié il y a quelques semaines un projet CodePlex permettant de générer et envoyer des newsletters à partir de contenu publié dans SharePoint 2010. Déjà présenté par Arnaud Jund, je ferai une démonstration live de son installation et de son utilisation lors du SharePoint Saturday.

Rendez-vous à 16H30 le 6 novembre prochain pour une session sur Winwise.SPMailing :)

Le site de l'évènement : http://www.sharepointsaturday.org/france

Arnault Nouvel
Winwise

SharePoint 2010 : Développer une web part d’authentification pour une page d’accueil

Nous avons vu dans un précédent billet comment configurer l’authentification par formulaire dans SharePoint 2010. Il est possible de développer son propre formulaire d’authentification afin d’en modifier le design et le comportement. Chun Liu propose un tutorial à cet effet : http://blogs.msdn.com/b/chunliu/archive/2010/08/21/creating-a-custom-login-page-for-fba-in-sharepoint-2010.aspx.

Je m’en suis inspiré pour développer une web part de login qui permet de s’authentifier en passant soit son login, soit son email. Mon autre objectif était de proposer l’authentification sur la page d’accueil du site, qui devait donc être en authentification anonyme. Ce billet détaille les étapes nécessaires pour parvenir à ce résultat.

Paramétrage de l’accès anonyme

Dans l’administration centrale : “Manage web applications”, sélectionner l’application web cible, cliquer dans le ruban sur “Authentication Providers”, sélectionner la zone cible, cocher “Enable Anonymous Access” et valider.

image

Dans la collection de sites : “Site Actions”, “Site Settings”, “Site permissions”, cliquer sur “Anonymous Access” dans le ruban, cocher “Entire Web Site” :

image

A ce stade, notre page d’accueil est accessible en authentification anonyme. Voyons maintenant comment développer une web part de login.

Développement de la web part

Avec Visual Studio 2010, créer un projet de type “Farm Solution”.

Pour manipuler les classes nécessaires à l’authentification en mode Claims, il est nécessaire d’ajouter 3 références au projet :

  • System.IdentityModel.dll (répertoire C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0)
  • Microsoft.IdentityModel.dll (répertoire C:\Program Files\Reference Assemblies\Microsoft\Windows Identity Foundation\v3.5)
  • Microsoft.SharePoint.IdentityModel.dll (à récupérer par ligne de commande dans C:\Windows\assembly\GAC_MSIL\System.IdentityModel\3.0.0.0__b77a5c561934e089)

Ajouter ensuite au projet une Visual Web Part

Code du fichier .ascx :

<table>

    <tr>

        <td>Login or email :&nbsp;</td>

        <td><asp:TextBox ID="txbLoginOrEmail" runat="server" Width="150px" TextMode="SingleLine" /></td>

    </tr>

    <tr>

        <td>Password :&nbsp;</td>

        <td><asp:TextBox ID="txbPassword" runat="server" Width="150px" TextMode="Password" /></td>

    </tr>

    <tr>

        <td colspan="2" align="right">

            <asp:Button ID="btnLogin" runat="server" Text="Login" OnClick="btnLogin_Click" />

        </td>

    </tr>

</table>

<asp:Label ID="lblError" runat="server" ForeColor="Red" EnableViewState="false" />

Code du fichier .ascx.cs :

    public partial class CustomAuthenticationWebPartUserControl : UserControl

    {

 

        //Validates an email adress

        private static Regex REGEX_EMAIL = new Regex(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", RegexOptions.Compiled | RegexOptions.IgnoreCase);

 

        protected void btnLogin_Click(object sender, EventArgs e)

        {

 

            //Retrieves a security token from supplied credentials

            SecurityToken token = GetSecurityTokenFromUserInput();

 

            if (token != null)

            {

 

                //Authenticates the user using the token

                SPFederationAuthenticationModule.Current.SetPrincipalAndWriteSessionToken(token);

 

                //Redirects user to current page or to previous page if there is a Source parameter in the query string

                //(Source parameter is set by SharePoint when redirecting to webapp's login page)

                SPUtility.Redirect(HttpContext.Current.Request.Url.ToString(), SPRedirectFlags.UseSource, HttpContext.Current);

               

            }

            else

                lblError.Text = "Invalid Credentials";

 

        }

 

       

        private SecurityToken GetSecurityTokenFromUserInput()

        {

           

            //Retrieves the SPFormsAuthenticationProvider associated to the current web application zone

            SPWebApplication webApp = SPWebApplication.Lookup(HttpContext.Current.Request.Url);

            SPIisSettings settings = webApp.IisSettings[SPContext.Current.Site.Zone];

            SPFormsAuthenticationProvider authProvider = settings.FormsClaimsAuthenticationProvider;

 

            //User input

            String login = txbLoginOrEmail.Text.Trim();

            String password = txbPassword.Text.Trim();

 

            //If the login input is an email, retrieves associated login using the membership provider

            if (REGEX_EMAIL.Match(login).Success)

            {

                MembershipProvider provider = Membership.Providers[authProvider.MembershipProvider];

                login = provider.GetUserNameByEmail(login);

            }

 

            //Returns the security token

            return SPSecurityContext.SecurityTokenForFormsAuthentication(HttpContext.Current.Request.Url, authProvider.MembershipProvider, authProvider.RoleProvider, login, password);

 

        }

 

    }

 

On notera qu’avec le claims authentication mode, on ne peut plus utiliser FormsAuthentication.Authenticate(login, password) comme on le faisait dans SharePoint 2007.

Après un Clic-droit + Deploy sur le projet, on peut positionner la web part sur la page d’accueil du site.

image

Cet exemple peut être téléchargé ici : SPCustomAuthenticationWebPart.zip

Custom Sign In Page

Lorsqu’un utilisateur non authentifié tente d’accéder à une ressource sécurisée, il est redirigé vers la page d’authentification dont l’url se paramètre au niveau web application. J’ai essayé de paramétrer la “Custom Sign In Page” sur l’url de la page d’accueil de mon site. Cependant, cela conduit à certains effets de bord désagréables. Par exemple, lorsqu’un utilisateur déjà authentifié accède à l’url de la “Custom Sign In Page” (la page d’accueil donc), SharePoint lève une erreur de sécurité.

En conjonction de d’une web part de login, je recommande donc de mettre en place un formulaire d’authentification personnalisé comme détaillé dans l’article de Chun Liu.

 

Arnault Nouvel – Winwise


Classé sous , ,

SharePoint 2010 : Configuration de l’authentification par formulaire avec annuaire AD-LDS (partie 4 – haute disponibilité de l’annuaire AD-LDS)

Ce billet fait partie d’une série :

Nous allons voir dans ce billet comment répliquer l’instance AD-LDS sur un second serveur et comment configurer la répartition de charge réseau afin d’assurer une haute disponibilité sur l’annuaire AD-LDS.

Voici les étapes :

  • Répliquer l’instance AD-LDS sur un deuxième serveur
  • Créer un cluster de répartition de charge
  • Rediriger le nom de domaine annuaire.extranet.test vers l’adresse IP du cluster

1. Installation d’une réplique de l’instance AD-LDS

Avec le même compte que le compte administrateur spécifié lors de la création de l’instance installé EXTRANET-ADLDS, se connecter au serveur EXTRANET-ADLDS2.

Après avoir installé le rôle “Active Directory Lightweight Directory Services”, lancer l’assistant de création d’instance comme nous l’avons fait dans la partie 2.

Sur le premier écran, choisir la 2ème option pour indiquer que l’on souhaite créer une réplique d’une instance existante :

23-replicat-install-adlds

Indiquer le serveur sur lequel se trouve l’instance à répliquer :

24-replica-choose-source

Sélectionner la partition à répliquer :

25-replica-choose-partition

Dérouler l’assistant jusqu’à la ce que la réplique soit créée.

Avec ADSIEdit.msc, il est possible de vérifier que l’instance est fonctionnelle (comme expliqué dans la partie 2), on retrouvera d’ailleurs les utilisateurs et groupes créés sur l’autre serveur.

Il faut cependant bien comprendre qu’on a là 2 instances différentes qui se synchronisent à intervalles réguliers.

2. Planification de la réplication

Démarrer la console “Active Directory Sites and Services” : Start, Administrative Tools, Active Directory Sites and Services.

Par défaut la console se connecte au domaine Active Directory du serveur. Nous allons lui demander de se connecter à notre instance AD-LDS via un clic-droit sur le noeud racine, puis “Change Domain Controller…”

image

Indiquer alors le nom d’un des serveurs (le principal ou la réplique, au choix) comme sur la capture suivante :

29-change-directory-server

Une fois connecté, on sélectionne le site “Default-First-Site-Name” et on ouvre les propriétés “NTDS Site Settings” :

image

Note : l’écran de propriétés n’est disponible que si le package MS-ADLDS-DisplayContainer.ldf a été importé lors de l’installation de l’instance principale.

L’écran des propriétés nous propose notamment de modifier la fréquence de réplication grâce à cette interface :

34-schedule

Nos 2 instances étant opérationnelles et répliquées, nous allons maintenant mettre en place la répartition de charge avec Windows NLB.

3. Planification de la répartition de charge avec Windows Network Load Balancing (NLB)

Pour schématiser, nous allons créer un cluster NLB qui correspondra à une IP virtuelle, et y associer les cartes réseau de nos 2 serveurs (EXTRANET ADLDS et EXTRANET-ADLDS2). Ces cartes réseau seront configurées par Windows NLB pour écouter les paquets adressés à l’adresse IP virtuelle du cluster.

La mise en place de ce système nécessite une planification.

Premièrement, il nous faut une adresse IP libre pour le cluster NLB.

Nous utiliserons ici l’adresse IP 192.168.70.10 pour notre cluster NLB, en sachant que EXTRANET-ADLDS utilise 192.168.70.11 et que EXTRANET-ADLDS2 utilise 192.168.70.12.

Dans la partie 2 nous avons créé un alias DNS annuaire.extranet.test qui pointe sur EXTRANET-ADLDS. Une fois la répartition de charge mise en place, nous modifieront l’entrée DNS pour qu’elle pointe vers l’IP du cluster au lieu de l’IP du serveur AD-LDS principal.

Ensuite, choisir son mode de fonctionnement :

  • En mode multicast, une carte réseau répond à la fois à son IP et à celle du cluster. Attention, certains équipements réseau (de vieux switchs par exemple) ne supportent pas ce mode. Avant de s’orienter sur ce mode, il faut vérifier si il est supporté par tous les équipements réseau situés entre les clients (le serveur SharePoint par exemple) et les serveurs cibles (AD-LDS).
  • En mode unicast, une carte réseau ne pourra répondre qu’aux paquets adressés au cluster, il faudra donc 2 cartes réseau par serveur du cluster.

Nous utiliserons ici le mode multicast qui est plus simple à mettre en place puisqu’il ne nécessite qu’une carte réseau par serveur.

Enfin, déterminer le “client affinity” qui correspond à la manière dont le NLB répartie les paquets provenant d’une même source :

  • None : les paquets sont envoyer aléatoirement à un ou l’autre des noeuds du cluster (le noeud cible reste le même pendant la durée de la session, une session étant lié à un port précis)
  • Single : une fois qu’un client (SharePoint par exemple) aura établit une première connexion à un noeud du cluster, les paquets suivants seront redirigés vers le même, quelque soit le port cible
  • Network : Le routage est fonction du sous-réseau de provenance du paquet

Nous utiliserons ici le mode Single.

4. Création du cluster NLB

Sur chaque serveur AD-LDS, via la console Server Manager, installer la fonctionnalité Windows appelée “Network Load Balancing” :

40-add-nlb-feature

Ensuite, se connecter sur le premier serveur AD-LDS (EXTRANET-ADLDS).

Exécuter la console d’administration du NLB : Cliquer sur Start, Administrative Tools, “Network Load Balancing Manager”.

Clic-droit sur le noeud racine, puis “New Cluster” :

41-creer-cluster

Saisir le nom du premier serveur à ajouter au cluster

42-creer-cluster-2

La fenêtre Host Parameters qui vient ensuite nous permet de spécifier un paramétrage pour le serveur indiqué précédemment. On indique la priorité du serveur au sein du cluster (la plus basse reçoit les paquets en priorité) et la ou les adresses IP qui feront partie du le cluster (un serveur peut avoir plusieurs cartes réseau).

42-cluster-host-parameters

La fenêtre “Cluster IP Adresses” permet de saisir la ou les adresses IP du cluster.

Nous allons ici ajouter l’adresse 192.168.70.10 qui est celle de notre cluster:

44-cluster-add-ip

La fenêtre “Cluster Parameters” permet de définir le host name à prendre en compte ainsi que le mode dont nous avons parlé plus haut, et ce pour chaque adresse IP. Indiquer annuaire.extranet.test pour le host name, et sélectionner le mode multicast :

45-cluster-parameters

L’écran suivant permet de définir quels ports seront pris en compte par le cluster. Par défaut, ils le sont tous.
Supprimer cette plage de port et n’indiquer que les ports 389 et 636 utilisés par nos instances AD-LDS. Pour chacun, sélectionner le protocole TCP et le Filtering mode “Single” :

46-cluster-ports

47-cluster-ports2

Nous avons à ce stade un cluster de répartition de charge qui contient un seul serveur, le EXTRANET-ADLDS. Nous allons maintenant ajouter le serveur EXTRANET-ADLDS2 au cluster.

Faire un clic-droit sur le cluster, “add host to cluster”, puis re dérouler les étapes précédentes pour ajouter le serveur EXTRANET-ADLDS2 :

48-cluster-final

La répartition de charge étant prête, il ne reste plus qu’à rediriger le nom de domaine annuaire.extranet.test vers l’adresse IP de notre cluster.

5. Redirection DNS

Les requêtes LDAP émanant de la ferme SharePoint sont effectuées sur le nom de domaine annuaire.extranet.test, qui pointe sur le serveur EXTRANET-ADLDS. Nous allons maintenant modifier l’entrée DNS annuaire.extranet.test pour qu’elle corresponde à l’adresse IP du cluster.

Se connecter au controlleur de domaine EXTRANET-AD avec le compte administrateur du domaine.

Ouvrir la console de gestion DNS : Start, Administrative Tools, DNS.

Déplier l’arborescence jusqu’au noeud extranet.test.

Supprimer l’alias annuaire (clic-droit, remove)

Créer une entrée de type Host (clic-droit, new Host) nommée annuaire pointant sur l’adresse IP du cluster : 192.168.70.10

image

A cause de son cache, le serveur SharePoint continue d’associer annuaire.extranet.test au serveur EXTRANET-ADLDS. Pour vider le cache DNS du serveur SharePoint afin qu’il associe annuaire.extranet.test à l’adresse IP du cluster NLB, il faut se connecter dessus et exécuter la ligne de commande suivante : ipconfig /flushdns

SharePoint communique désormais avec un annuaire AD-LDS assurant une haute disponibilité. On peut s’amuser à éteindre et rallumer les serveurs AD-LDS un par un et vérifier que l’authentification fonctionne toujours.

 

Arnault Nouvel – Winwise

SharePoint 2010 : Configuration de l’authentification par formulaire avec annuaire AD-LDS (partie 3 – configuration de l’authentification par formulaire)

Ce billet fait partie d’une série :

Ce tutorial requiert que SharePoint 2010 soit installé, que la partition AD-LDS qui contient nos utilisateurs aie été configurée, et que les comptes de services utilisés par SharePoint y aient accès en lecture. Pour les détails, voir partie 2.

Nous allons maintenant créer une nouvelle application web SharePoint en authentification par formulaire.

1. Creation de l'application web

L'authentification par formulaire sous SharePoint 2010 repose toujours sur le système du MembershipProvider hérité d'ASP.NET, qui permet de générer une identité à partir d'un système tiers. On ne pourra cependant utiliser l'authentification par formulaire que si on configure notre application web en mode claims.

Dans l'administration centrale, cliquer sur le lien "Manage Web Applications". Dans le ruban, cliquer sur "New" pour ouvrir la fenêtre de création d'application web.

On coche "Claims authentication mode", on indique optionnellement un nom de domaine (nécessite de définir un alias DNS), et dans la partie claims authentication on coche "Forms Authentication Mode" en indiquant un nom pour le membership provider et un autre pour le role provider.

18-creation-webapp-1

19-creation-webapp-2

On ne décochera pas “Windows Authentication” sous peine de ne pas pouvoir faire fonctionner la recherche.
Un contournement possible pour ne pas avoir l’authentification Windows tout en conservant la recherche serait de passer par une extension d’application web : une application web avec authentification Windows pour la recherche, une autre avec authentification par formulaire pour les utilisateurs.

Nous allons maintenant devoir expliquer à SharePoint à quoi correspondent “AdldsMember” et “AdldsRole”. En l'occurrence nous allons les associer au LdapMembershipProvider fournit avec SharePoint Server 2010 qui permet d'exploiter LDAP générique. Il est donc parfaitement adapté à AD-LDS.

Ce paramétrage s’effectue au niveau des fichiers web.config des applications web suivantes :

  • Administration centrale
  • Secure Store Service
  • L’application web que nous venons de créer

 

2. Modification du web.config de l'administration centrale

Ouvrir le fichier C:\inetpub\wwwroot\wss\VirtualDirectories\55555\web.config (55555 correspondant au numéro de port de l'administration centrale, il varie d'un environnement à l'autre).

Remplacer les nœuds membership et roleManager par le bloc suivant :

<membership>

   <providers>

      <add name="AdldsMember"    

           type="Microsoft.Office.Server.Security.LdapMembershipProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

           server="annuaire.extranet.test"

           port="389"

           useSSL="false"

           userDNAttribute="distinguishedName"

           userNameAttribute="cn"

           userContainer="OU=Users,OU=extranet,DC=annuaire,DC=extranet,DC=test"

           userObjectClass="user"

           userFilter="(ObjectClass=user)"

           scope="Subtree"

           otherRequiredUserAttributes="sn,givenname,cn" />

  </providers>

</membership>

<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider" >

   <providers>

      <add name="AdldsRole"

            type="Microsoft.Office.Server.Security.LdapRoleProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

            server="annuaire.extranet.test"

            port="389"

            useSSL="false"

            groupContainer="OU=Users,OU=extranet,DC=annuaire,DC=extranet,DC=test"

            groupNameAttribute="cn"

            groupNameAlternateSearchAttribute="cn"

            groupMemberAttribute="member"

            userNameAttribute="cn"

            dnAttribute="distinguishedName"

            groupFilter="(ObjectClass=group)"

            userFilter="(ObjectClass=user)"

            scope="Subtree" />

   </providers>

</roleManager>

Afin de faire fonctionner la filtrage dans le sélecteur de personnes, une modification nécessaire s’impose.
Dans le nœud PeoplePickerWildcards, ajouter les entrées pour AdldsMember et AdldsRole comme indiqué ci-dessous :

<PeoplePickerWildcards>

      <clear />

      <add key="AspNetSqlMembershipProvider" value="%" />

      <add key="AdldsMember" value="*" />
      <add key="AdldsRole" value="*" />
</PeoplePickerWildcards>

Seules les parties surlignées en jaunes sont à modifier en fonction l'annuaire cible.

Enregistrer le fichier.

3. Modification du web.config du Secure Store Service

Ouvrir le fichier : C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebServices\SecurityToken\web.config

A l’intérieur du nœud <configuration>, copier le XML suivant :

<membership>

   <providers>

        <add name="AdldsMember"

             type="Microsoft.Office.Server.Security.LdapMembershipProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

             server="annuaire.extranet.test"

             port="389"

             useSSL="false"

             userDNAttribute="distinguishedName"

             userNameAttribute="cn"

             userContainer="OU=Users,OU=extranet,DC=annuaire,DC=extranet,DC=test"

             userObjectClass="user"

             userFilter="(ObjectClass=user)"

             scope="Subtree"

             otherRequiredUserAttributes="sn,givenname,cn" />

   </providers>

</membership>
<roleManager enabled="true" defaultProvider="AdldsRole" >

   <providers>

        <add name="AdldsRole"

             type="Microsoft.Office.Server.Security.LdapRoleProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

             server="annuaire.extranet.test"

             port="389"

             useSSL="false"

             groupContainer="OU=Users,OU=extranet,DC=annuaire,DC=extranet,DC=test"

             groupNameAttribute="cn"

             groupNameAlternateSearchAttribute="cn"

             groupMemberAttribute="member"

             userNameAttribute="cn"

             dnAttribute="distinguishedName"

             groupFilter="(ObjectClass=group)"

             userFilter="(ObjectClass=user)"

             scope="Subtree" />

   </providers>

</roleManager>

 

Enregistrer le fichier.

4. Modification du web.config de l'application web

Ouvrir maintenant le fichier web.config de l'application web créée plus haut : C:\inetpub\wwwroot\wss\VirtualDirectories\portail.extranet.test80\web.config (le nom du répertoire change en fonction du host header et du numéro de port)

A l'intérieur du nœud membership, copier le XML suivant (en conservant les autres nœuds existants):

<add name="AdldsMember"

     type="Microsoft.Office.Server.Security.LdapMembershipProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

     server="annuaire.extranet.test"

     port="389"

     useSSL="false"

     userDNAttribute="distinguishedName"

     userNameAttribute="cn"

     userContainer="OU=Users,OU=extranet,DC=annuaire,DC=extranet,DC=test"

     userObjectClass="user"

     userFilter="(ObjectClass=user)"

     scope="Subtree"

     otherRequiredUserAttributes="sn,givenname,cn" />

A l'intérieur du nœud roleManager, copier le XML suivant (en conservant les autres nœuds existants):

<add name="AdldsRole"

     type="Microsoft.Office.Server.Security.LdapRoleProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

     server="annuaire.extranet.test"

     port="389"

     useSSL="false"                   

     groupContainer="OU=Users,OU=extranet,DC=annuaire,DC=extranet,DC=test"

     groupNameAttribute="cn"

     groupNameAlternateSearchAttribute="cn"

     groupMemberAttribute="member"

     userNameAttribute="cn"

     dnAttribute="distinguishedName"

     groupFilter="(ObjectClass=group)"

     userFilter="(ObjectClass=user)"

     scope="Subtree" />

 

Dans le nœud PeoplePickerWildcards, ajouter les entrées pour AdldsMember et AdldsRole comme indiqué ci-dessous :

<PeoplePickerWildcards>

      <clear />

      <add key="AspNetSqlMembershipProvider" value="%" />

      <add key="AdldsMember" value="*" />
      <add key="AdldsRole" value="*" />
</PeoplePickerWildcards>

Enregistrer le fichier, puis éxecuter iisreset.exe.

5. Création de la collection de sites racine de l'application web

Naviguer dans l'administration centrale dans "Applications management", et cliquer sur "Create Site Collection". Sélectionner l'application web pour laquelle nous avons configuré l'authentification par formulaire, et donner un nom à la collection de sites.

Ouvrir la fenêtre de sélection d'utilisateur pour définir l'administrateur de la collection de sites, on retrouve alors nos utilisateurs de l’annuaire AD-LDS dans la catégorie "Forms Auth". Sélectionner user1, et valider la création de la collection de sites.

20-sitecoladmin

Se connecter maintenant à l'application web (dans l'exemple, http://portail.extranet.test). On nous propose alors de choisir un mode d'authentification, choisir "Forms Authentication" puis saisir les credentials de user1.

21-auth

22-auth2

23-auth3

L’authentification par formulaire est maintenant opérationnelle.

Bien qu’optionnelle vis à vis de l’authentification par formulaire, la 4ème partie de cette série de billets explique comment répliquer l’instance AD-LDS sur un second serveur et comment configurer la répartition de charge réseau afin d’assurer une haute disponibilité sur l’annuaire AD-LDS : Partie 4 : haute disponibilité de l’annuaire AD-LDS

 

Arnault Nouvel – Winwise

SharePoint 2010 : Configuration de l’authentification par formulaire avec annuaire AD-LDS (partie 2– installation et configuration de AD-LDS)

Ce billet fait partie d’une série :

Dans ce billet, nous allons mettre en place un annuaire AD-LDS sur un seul serveur, le serveur EXTRANET-ADLDS. La haute disponibilité AD-LDS étant optionnelle, elle sera traitée comme telle en partie 4.

1. Paramétrage DNS

Avant de créer l'instance, nous allons créer un alias DNS annuaire.extranet.test qui permettra à SharePoint de connaitre l'IP de la machine qui héberge l'annuaire. Cette étape est optionnelle puisque l’on pourrait utiliser le nom du serveur EXTRANET-ADLDS.extranet.test, cependant cet alias nous permettra de ne pas avoir à reconfigurer l’authentification par formulaire lorsque nous mettrons en place la haute disponibilité dans la partie 4.

Connectons nous au contrôleur de domaine EXTRANET-AD avec le compte administrateur du domaine. Dans la console d'administration du DNS (Administrative Tools -> DNS), ajoutons un alias appelé "annuaire" qui pointe sur le serveur EXTRANET-ADLDS.

0-dns

Connectons nous maintenant au serveur EXTRANET-ADLDS avec le compte spadmin (qui est administrateur de la machine).

2. Installation de rôle AD-LDS

Afin de pouvoir créer une instance AD-LDS, il est nécessaire d'installer le rôle Active Directory Lightweight Directory Services.

Via la console Server Manager, ajoutons ce rôle :

1-ajout-role-adlds 

3. Création de l'instance AD-LDS

Une fois l'installation terminée, la console Server Manager dispose d'un nœud Roles/ADLDS et propose de créer une instance via le lien en haut à droite, cliquons dessus pour lancer l'assistant.

2-creation-instance-adlds

3-creation-instance-adlds

Donner un nom à l'instance, ce nom définit celui du service Windows correspondant :

4-nom-instance-adlds

Dans notre cas, on laissera les ports par défaut :

5-ports-adlds

On indique ensuite que l'on souhaite créer une partition racine pour notre annuaire. Par convention, le nom de la partition reprend tout ou partie du nom de domaine du serveur LDAP. Bien que cela n’aie rien d’obligatoire, le "Distinguished Name" de notre partition se terminera par "DC=annuaire,DC=extranet,DC=test" afin d’établir une correspondance avec notre alias DNS annuaire.extranet.test. Plus d’informations sur les conventions de nommage des partitions : http://technet.microsoft.com/en-us/library/cc784421(WS.10).aspx

Afin que la racine de la partition soit une "Organisational Unit" (là encore rien d'obligatoire, il y a d'autres options), nous allons nommer celle-ci "OU=extranet,DC=annuaire,DC=extranet,DC=test" :

6-creation-partition-adlds

L'écran suivant permet de sélectionner le compte de service utilisé par le service Windows correspondant à l'instance.

7-service-account-adlds

On sélectionne ensuite quel compte ou groupe Active Directory sera administrateur de l'instance : 

8-admin-adlds

Enfin, on sélectionne quels packages de définition seront importés dans notre instance AD-LDS :

  • MS-user.ldf car il définit la classe “user” que nous allons utiliser
  • MS-ADLDS-DisplayContainers.ldf qui permet d’administrer une instance AD-LDS avec la console Active Directory Sites and Services (utile pour planifier la réplication)

9-ldif-adlds

Un point intéressant à noter est la disponibilité du package MS-UserProxy qui permet de créer des utilisateurs bindés sur des comptes utilisateurs d'un autre annuaire LDAP ou Active Directory. Plus d'informations : http://technet.microsoft.com/en-us/library/cc775757(WS.10).aspx

En déroulant la fin de l’assistant, notre partition racine sera créée. Nous allons maintenant nous y connecter et remplir notre annuaire.

4. Connexion à l'annuaire AD-LDS

Bien que nous ayons créé un alias DNS annuaire.extranet.test spécifiquement pour notre connexion à l’instance AD-LDS, nous n’allons pas l’utiliser avant la partie 3. En effet, durant l'installation de l'AD-LDS, une clé de registre a été modifiée afin d'empêcher toute connexion au serveur local en utilisant un alias DNS (la fameuse clé DisableLoopbackCheck). Nous pouvons toutefois nous connecter à notre instance en local en utilisant le nom de serveur LOCALHOST ou EXTRANET-ADLDS. 

Ouvrons maintenant ADSIEdit (Start, run, "adsiedit.msc") et ajoutons une connexion :

  • Saisir le “distinguished name” de la partition racine dans la combo du haut
  • Saisir EXTRANET-ADLDS du dans la combo du bas

Notre chaine de connexion est donc : LDAP://EXTRANET-ADLDS/OU=extranet,DC=annuaire,DC=extranet,DC=test

11-adsiedit-connection-adlds

En validant, ADSIEdit nous dévoile la structure de notre partition.

12-structure-partition 

5. Création des utilisateurs

Nous allons créer une OU pour regrouper nos utilisateurs et groupes de sécurité : clic-droit sur l’OU racine, new, “object...”, organisationalUnit, puis saisir un nom pour l’OU.

Ici, on crée une OU appelée “Users”.

13-create-ou

Nous allons maintenant créer un utilisateur “user1”. Pour créer un utilisateur dans l'OU Users, suivre les étapes suivantes :

  • Clic-droit sur l'OU Users, new, “object…”, user. On lui donne alors le nom “user1”.
  • Click-droit sur le compte, "Reset Password…", on définit alors son mot de passe.

14-create-user-password

  • Enfin et surtout, on active le compte en double cliquant dessus pour afficher ses propriétés et en modifiant le champ ms-UserAccountDisabled qui est par défaut à TRUE. On le met à FALSE afin d'activer le compte.

15-enable-user

Note : On utilisera aussi cet écran de propriétés pour définir le nom d'affichage de l'utilisateur (champ displayName), son email (champ mail), et autres informations nécessaires.

Pour les besoins du tutorial, répéter ces 3 étapes afin de créer un autre utilisateur appelé user2.

6. Création d’un groupe

Créons maintenant un groupe via un clic-droit sur l'OU Users, new, Object…, group.

Pour ajouter des utilisateurs dans ce groupe, on ouvre la fenêtre des propriétés du groupe et on édite le champ "member" dans lequel on indique le distinguished name de chaque utilisateur à ajouter. Sur la capture suivante, on ajoute l'utilisateur user1 dans le groupe group1.

16-add-user-to-group

Note : pour éviter une erreur de saisie, une astuce consiste à faire un copier coller de la valeur du champ distinguishedName depuis l'écran des propriétés de l'utilisateur.

7. Configuration des droits d’accès à la partition

Avant de passer à la configuration de l’authentification par formulaire dans SharePoint, nous devons autoriser les comptes de service de SharePoint à se connecter en lecture à l'annuaire.

Déplier le nœud CN=Roles et double cliquer sur CN=Readers pour afficher ses propriétés. Dans le champ "member", on ajoute les comptes Active Directory des différents comptes de service qui en auront besoin :

  • Application pool de l'administration centrale
  • Application pool de la web application qui héberge le portail
  • Application pool du Secure Token Service

Afin de simplifier et d'éviter toute erreur dans le cadre du tutorial, nous allons ici ajouter le groupe "EXTRANET\Users" qui en principe les contient tous.

17-readers-adlds

Notre annuaire utilisateur est maintenant prêt à être utilisé par notre portail SharePoint 2010 : les comptes de service SharePoint sont autorisés à s'y connecter, et nous disposons de 2 utilisateurs de test dont un dans un groupe.

Passons maintenant à la configuration de l’authentification par formulaire sous SharePoint : Partie 3 : configuration de l’authentification par formulaire

 

Arnault Nouvel – Winwise


Classé sous ,

SharePoint 2010 : Configuration de l’authentification par formulaire avec annuaire AD-LDS (partie 1– introduction)

Ce billet fait partie d’une série :

Je travaille en ce moment sur la mise en place d'un portail extranet client en SharePoint 2010 dont l'infrastructure est intéressante. Cet extranet propose aux clients de manipuler des données provenant de divers systèmes d'informations existants mais hétérogènes, notamment du SAP. Afin de fournir à SharePoint un back-end unique pour manipuler les données, une infrastructure de web services SOA est développée en parallèle du portail. Celle-ci est hébergée sur une plateforme IBM WebSphere (contrainte client) qui se charge d’agréger les données à partir des back-ends existants. 

3 équipes ont été mises en place et travaillent de concert :

  • Une équipe chargée d'effectuer les adaptations nécessaires dans les différents S.I. cibles
  • Une équipe en charge de la mise en place de la plateforme SOA
  • Une équipe en charge de la mise en place et de la réalisation du portail extranet

Mon rôle dans ce projet est de définir l'architecture du portail et de mettre en place l’infrastructure qui va avec.

Nous tirons partie de plusieurs des nouvelles fonctionnalités de SharePoint Server 2010 : les claims et le Secure Store Service pour la délégation d’identité, et le Business Data Connectivity Service qui permet à SharePoint de manipuler aisément des données provenant de systèmes externes. Dans notre cas les données proviennent des web services de la plateforme S.O.A.

Pour des raisons évidentes de sécurité, les Web Services ont besoin de connaitre l’identité de l’utilisateur courant afin de l’autoriser ou non en lecture et en écriture sur les divers objets métiers. L'annuaire utilisateur doit donc être partagé entre SharePoint 2010 (authentification et autorisations d’accès au portail) et la plateforme SOA (autorisations d’accès aux objets métiers).

Livré avec Windows 2008 R2, Active Directory LightWeight Services (AD-LDS) fournit un annuaire LDAP standard qui est exploitable à la fois par SharePoint 2010 et par les web services WebSphere. Il permet aussi d'assurer une haute disponibilité grâce à son système de réplication. Tous ces points étant des pré-requis du projet, nous avons adopté AD-LDS.

Ci dessous un schéma macroscopique de l’infrastructure globale :

 

infrastructure-macro

 

Dans cette série de billets, nous allons nous concentrer sur la mise en place d’un annuaire utilisateurs dans AD-LDS et de l'authentification par formulaire sur SharePoint Server 2010. Nous configurerons ensuite la haute disponibilité au niveau d’AD-LDS en ajoutant un autre serveur et en utilisant le Windows Network Load Balancing (NLB).  Dans le projet en question tous les nœuds applicatifs bénéficient de haute disponibilité (3 frontaux SP, cluster SQL, etc.), mais ici nous ne nous intéresseront qu’à sa mise en place sur AD-LDS.

Voici l'infrastructure sur laquelle je me suis appuyé pour réaliser ce tutorial :

infrastructure-test

Les 5 serveurs font partie d'un même domaine Active Directory extranet.test. Ce domaine contient les comptes de services utilisés par SharePoint 2010 et SQL Server, et les comptes utilisateurs des administrateurs des serveurs. Les utilisateurs distants qui pourront se connecter au portail extranet seront, eux, définis dans l'annuaire AD-LDS, ce qui permet en outre de ne pas polluer l'AD principal.

Contexte de départ :

  • Les 5 serveurs sont des Windows 2008 R2 et font partie du domaine extranet.test
  • Le compte EXTRANET\spadmin est administrateur de tous les serveurs
  • SQL Server 2008 R2 est installé
  • SharePoint Server 2010 est installé en mode ferme et configuré selon les “best-practices” (avec des comptes de service dédiés pour les application pools, etc)

Passons maintenant à l'installation et à la configuration de l'annuaire AD-LDS : Partie 2 - installation et configuration de AD-LDS

Arnault Nouvel – Winwise

SharePoint 2010 : Personnaliser la XSLT List View Web Part

sharepoint-server

Dans la version 2007 de SharePoint, la List View web part proposait la sélection d’une liste et d’un affichage de la liste choisie. Optionnellement, on pouvait modifier la vue pour par exemple afficher une colonne supplémentaire.

Dans SharePoint 2010, cette web part est remplacée par la XSLT List View Web Part. Celle-ci conserve ces fonctionnalités, mais permet en plus de modifier le rendu HTML grâce à une transformation XSL personnalisable. Ce mécanisme permet de redéfinir entièrement le rendu des données issues d’une liste SharePoint, en ayant le contrôle sur la requête CAML sous-jacente. Un vrai couteau suisse :)

Dans ce billet, nous allons voir comment modifier la requête CAML sous-jacente, comment personnaliser la transformation XSLT qui assure le rendu HTML, et comment déporter cette transformation dans un fichier xslt. En effet, par défaut le XSL customisé est stocké en propriété de la web part, mais il est  possible de l’enregistrer dans un fichier séparé afin de le réutiliser pour plusieurs web parts.

Le tout sera fait avec l’interface web classique et SharePoint Designer.

Créons tout d’abord une liste d’annonces, puis ajoutons la web part correspondante sur la page d’accueil.

image

A ce stade, la XSLT List View Web part exploite la transformation XSLT “out of the box”. Voyons comment modifier la requête CAML et le rendu avec SharePoint Designer. Pour cela on sélectionne la web part, puis dans l’onglet “Liste” on demande la modification de l’affichage avec SharePoint Designer, comme sur cette capture :

image  

SharePoint Designer s’ouvre alors en modification sur la page courante afin de nous permettre de modifier la définition de la web part. On constate que la requête CAML sous-jacente est embarquée dans la définition de la web part.

image

Modifions cette requête CAML pour y supprimer les colonnes Attachments et Modified, et ajoutons la colonne Body :

image

On peut alors enregistrer et constater le changement dans le navigateur :

image

Cette possibilité existait déjà avec SharePoint 2007. Voyons maintenant comment modifier le rendu HTML en personnalisant la transformation XSLT, ceci étant une nouveauté de la version 2010.

Dans SharePoint Designer, on sélectionne la web part et dans l’onglet « Design » on clique sur « Customize XSLT -> Customize entire view »

image

La définition de la web part est alors modifiée et contient la transformation XSLT.

image

Celle-ci est très verbeuse car il s’agit de la transformation native qui permet un affichage dynamique en fonction des colonnes sélectionnées quel que soit la requête CAML sous-jacente. On y trouve aussi des appels à des fonctions javascript qui permettent la multi-sélection, le rafraîchissement automatique Ajax et autres fonctionnalités natives des listes SharePoint.

Nous allons maintenant externaliser cette transformation dans un fichier xslt séparé. Cela permet une édition plus pratique et apporte la possibilité versionner, approuver et surtout de réutiliser la transformation dans plusieurs XSLT List View Web Parts. Cette étape est optionnelle car il est possible de modifier la transformation directement dans la définition de la web part, mais je tenais à mettre en avant cette possibilité dans ce billet.

Copions tout le contenu de la balise <xsl></xsl> dans un fichier CustomAnnonces.xslt, et uploadons ce fichier dans la bibliothèque Style Library du site.

image

Maintenant que le fichier contenant la transformation XSLT est enregistré dans le site SharePoint, nous devons indiquer à la XSLT List View Web Part l’url du fichier xslt à utiliser. Pour cela, dans le navigateur, on modifie les propriétés de la web part et on spécifie l’url relative serveur du fichier dans le champ « Lien XSL » de la section « Divers ».

image

A ce stade, on peut travailler dans SharePoint Designer pour modifier la transformation CustomAnnonces.xslt. A chaque modification, on peut enregistrer le fichier et rafraichir son navigateur pour constater le changement.

Il n’est pas toujours nécessaire de conserver les centaines de lignes de la transformation XSLT par défaut. La transformation native dite « schema independant » s’appuie sur la requête CAML (passée en paramètre de la transformation) pour renvoyer un rendu HTML en fonction des colonnes sélectionnées dans l’affichage. Plus d’informations sur cette logique « schema independant » sont disponibles dans ce billet : SharePoint 2010 List View Blog Series: Part 3 – List View Architecture.

Pour l’exemple, je ne veux afficher que le champ titre et le champ body avec un rendu HTML très simple sous forme de balises ul / li, et je n’ai pas besoin de conserver les fonctionnalités natives que sont le filtrage dynamique, la multi sélection, etc.

On peut vider le contenu de la balise principale et redéfinir la transformation comme on le souhaite :

custom xslt

Après enregistrement, voici le résultat dans le navigateur :

rendu personnalisé

 

Au travers de cet exemple simpliste, nous avons vu comment avec SharePoint Designer :

- Personnaliser la requête CAML sous-jacente d’une XSLT List View Web Part

- Personnaliser la transformation XSLT assurant le rendu HTML

- Externaliser la transformation XSLT dans un fichier séparé

Avec une mise en forme CSS et un peu de JavaScript, les possibilités de cette web part peuvent devenir très intéressantes puisqu’elle permet de répondre à énormément de besoins métiers sans nécessiter le déploiement de code serveur. Cette web part va sans nul doute faire beaucoup parler d’elle dans les mois à venir.

 

Arnault Nouvel - Winwise

SharePoint 2010 : Configuration du courrier sortant et du courrier entrant dans une machine virtuelle

sharepoint-server

Utile pour certaines démonstrations, formations, ou pour des développements spécifiques, la configuration du courrier entrant et sortant dans une machine virtuelle SharePoint 2010 n’est plus aussi aisée qu’auparavant. En effet, le serveur mail de Windows Server 2003 n’a pas été porté dans les éditions 2008 et 2008 R2 de Windows Server, seul le serveur SMTP a été conservé.

Nous allons voir comment configurer le mail sortant et le mail entrant dans une machine virtuelle SharePoint 2010 disposant de l’environnement logiciel suivant :

  • Windows Server 2008 R2 (nom de machine : SPF2010)
  • Active Directory Domain Services (nom de domaine : office14.local)
  • SQL Server 2008 R2
  • SharePoint Foundation 2010
  • Office Professional 2010

Pour mettre en place le courrier entrant et le courrier sortant sur la même machine virtuelle, l’astuce va consister à utiliser conjointement :

  • un serveur mail complet (SMTP + IMAP) pour les boites mail de nos utilisateurs ainsi que pour le courrier sortant (hMailServer)
  • le serveur SMTP de Windows Server pour le courrier entrant

Nous allons tout d’abord installer un serveur mail gratuit téléchargeable sur internet : hMailServer. Celui-ci fera office de serveur mail pour nos utilisateurs ainsi que de serveur SMTP pour le courrier sortant.

 

1. Configuration de hMailServer

hMailServeur est disponible au téléchargement à l’adresse suivante : http://www.hmailserver.com/

Installer hMailServer en laissant toutes les options par défaut.

Une fois hMailServer installé, connectons nous à son interface d’administration intitulée hMailServer Administrator :

hMailServer-ajout-domaine1

Via le bouton « Add domain… », ajoutons le domaine office14.local correspondant au domaine de notre Active Directory.

hMailServer-ajout-domaine1

La seule information à spécifier est le nom du domaine.

Configurons maintenant le serveur mail pour y désactiver certains paramètres de sécurité qui pourraient nous gêner pour la suite :

Dans Settings -> Advanced -> Auto-ban : décocher la case “enabled” et enregistrer.

hMailServer-autoban

Dans Settings -> Advanced -> IP Ranges -> Internet, décocher les cases concernant l’authentification du serveur SMTP, puis enregistrer :

hMailServer-auth

Notre serveur de messagerie est maintenant opérationnel.

 

2. Configuration DNS

Nous allons configurer le DNS afin qu’Outlook puisse configurer automatiquement les adresses de messagerie correspondant au nom de domaine office14.local.

Avant tout, vérifions dans les propriétés de la carte réseau que son serveur DNS principal est le serveur DNS local

dns-principal

Créons ensuite une entrée MX dans le DNS Manager (Tous les programmes -> outils d’administration –> DNS).

dns-mx

On laissera le premier champ vide afin de créer une entrée MX par défaut, et on sélectionnera le host correspondant à notre machine virtuelle dans le 2ème champ :

dns-mx2

La configuration nécessaire est maintenant effectuée. Créons un compte de messagerie administrator@office14.local pour l’utilisateur OFFICE14\Administrator.

 

3. Création de boites de messagerie

hMailServer permet de créer automatiquement des boites de messagerie pour les utilisateurs enregistrés dans l’Active Directory.

Pour chaque utilisateur de l’Active Directory pour lequel on souhaite créer une boite mail, nous allons suivre la procédure suivante :

Click droit sur le noeud Accounts, puis “Add AD Account”.

hMailServer-ajout-utilisateur

On sélectionne les utilisateurs pour lesquels on souhaite créer une boite de messagerie.

hMailServer-ajout-utilisateur2

Pour chaque utilisateur pour lequel on crée boite de messagerie, on inscrira l’adresse de messagerie correspondante dans l’Active Directory :

AD-user-mail

On peut maintenant ouvrir Outlook 2010 pour configurer le compte administrator@office14.local.

outlook-configuration-utilisateur

Grâce à la configuration DNS mise en place précédemment, l’assistant va configurer automatiquement le compte de messagerie :

outlook-configuration-utilisateur2

On répètera cette procédure pour tous les comptes utilisateurs pour lesquels on souhaite disposer d’une boîte de messagerie dans Outlook 2010.

 

4. Configuration de SharePoint 2010 pour le courrier sortant

Le courrier sortant permet à SharePoint d’envoyer des emails aux utilisateurs (alertes sur les listes, quotas, etc.). Voyons comment le configurer.

Dans l’administration centrale de SharePoint, cliquer sur « System Settings » puis « Configure Outgoing E-Mail Settings »

Indiquer le nom de la machine virtuelle comme sur la capture, ainsi que l’adresse mail au nom de laquelle SharePoint enverra des mails :

sharepoint-courrier-sortant

Pour tester, le plus simple est de créer une alerte avec l’utilisateur Administrator sur n’importe quelle liste SharePoint, car lors de sa création un email de confirmation est envoyé instantanément.

On vérifiera tout d’abord que SharePoint connait l’email associée au compte utilisateur Administrator, dans ses paramètres personnels :

sharepoint-mail-utilisateur

Ensuite on crée une alerte sur une liste (la liste Resources dans l’administration centrale par exemple).

sharepoint-creer-alerte

On constate alors dans Outlook 2010 que SharePoint a envoyé un message à administrator@office14.local 

confirmation-alerte

 

5. Configuration du serveur SMTP pour le courrier entrant

Le courrier entrant est une fonctionnalité très intéressante de SharePoint puisqu’il permet de créer du contenu dans des listes et bibliothèques SharePoint à partir de mails envoyés par les utilisateurs. Pour le mettre en place, il faudra créer un sous-domaine (ici sharepoint.office14.local) réservé à cette usage et le router vers un serveur SMTP dédié.

Nous allons pour cela configurer le serveur SMTP de Windows Server. En effet, le SMTP de hMailServer utilise une structure de fichier qui ne pourrait pas convenir à SharePoint.

Pour installer le serveur SMTP de Windows Server, on utilise l’écran d’ajout de feature Windows :

smtp-feature

Une fois la feature installée, on peut ouvrir la console d’administration de IIS 6.0 pour y configurer l’instance SMTP.

Le port 25 étant déjà utilisé par hMailServer, nous allons devoir configurer le SMTP sur un port différent : ici, le port 6925.

Clic-droit sur le noeud SMTP Virtual Server –> Properties -> bouton Advanced –> Edit :

configuration-smtp

Ensuite, on modifie le nom de domaine par défaut pour qu’il corresponde au sous-domaine que l’on souhaite réserver pour les adresses mails des listes SharePoint. Ici, on utilisera sharepoint.office14.local :

configuration-smtp-domaine

On peut alors démarrer le serveur SMTP.

smtp-start

Une chose importante reste à faire dans hMailServer. Il faut router les emails dont les destinataires sont xxxxx@sharepoint.office14.local vers le serveur SMTP Windows, en précisant le port 6925, comme indiqué dans la capture :

hMailServer-routage

 

6. Configuration de SharePoint 2010 pour le courrier entrant

Dans l’administration centrale, cliquer sur « System Settings », puis « Configure incoming e-mail settings ». Puisque nous hébergeons localement le serveur SMTP, il suffit de sélectionner le mode automatique et de préciser le sous-domaine choisi pour les adresses mails :

sharepoint-courrier-entrant

Pour tester, associons une adresse mail à une bibliothèque de documents. Dans les paramètres de la bibliothèque de documents de l’administration centrale, cliquer sur « Incoming e-mail settings ».

On peut alors associer une adresse de messagerie à la bibliothèque :

sharepoint-courrier-entrant-bibliotheque

Pour tester, nous allons ouvrir Outlook et écrire un mail à notre bibliothèque de documents, avec en pièces jointes les documents que l’on souhaite y envoyer :

courrier-entrant-test

Par défaut, le job SharePoint qui va récupérer les messages dans le drop folder du serveur SMTP s’exécute toutes les minutes. Il faut donc patienter quelques secondes avant que le document apparaisse dans la bibliothèque :

courrier-entrant-test2

 

Conclusion

Dans ce billet, nous avons vu comment mettre en place le courrier entrant et le courrier sortant sur une seule machine virtuelle, en utilisant conjointement un serveur mail gratuit et le serveur SMTP de Windows Server. Nous avons aussi vu comment créer des boites de messageries pour les utilisateurs de notre Active Directory, et comment les configurer dans Outlook 2010.

Je n’ai trouvé aucun serveur mail gratuit permettant de gérer le courrier entrant, n’hésitez pas à laisser un commentaire si vous en connaissez un.

 

Arnault Nouvel - Winwise

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!

Plus de Messages Page suivante »

Les 10 derniers blogs postés

- MBA : Pourquoi faire et comment le choisir ? par Blog Technique de Romelard Fabrice le il y a 15 heures et 13 minutes

- Y'a des erreurs qui peuvent rendre le développeur violent par Aleks's Blog le 02-02-2012, 16:33

- [Hyper-V 3] Présentation des commandlets PowerShell par Blog de SPBrouillet (Pierrick BROUILLET) le 01-31-2012, 16:01

- IIS7 – Compression GZIP par Atteint de JavaScriptite Aiguë [Cyril Durand] le 01-31-2012, 15:52

- SharePoint 15 Technical Preview Managed Object Model Software Development Kit par Matthew le 01-31-2012, 12:34

- Office 15 Technical Preview - Open specification Update par Matthew le 01-31-2012, 10:14

- TFS Integration Tools – Installation par Vivien Fabing le 01-31-2012, 00:06

- Test par RonnyK le 01-30-2012, 16:56

- [SharePoint 2010] Désactiver le correcteur orthographique dans les pages d’un site de publication par Jean-Christophe Brabant le 01-30-2012, 09:30

- [SharePoint 2010] Site internet et performances : poids et nombre des ressources par Arnault Nouvel le 01-30-2012, 00:52