I. Introduction▲
Le but de cet article est de montrer une autre manière d'intégrer des contrôles personnels dans Sharepoint. La manière la plus fréquente est le développement de webparts que l' on intègre ensuite dans des pages. Pour toute information sur les webparts, vous pouvez consulter les tutoriaux suivants:
- Déploiement d'un webpart personnel dans Sharepoint
- Utilisation et connexion de WebParts
- Ecrire un webpart pour Sharepoint avec Smartpart
- Aller plus loin avec les webparts Sharepoint
Nous allons créer un contrôle personnel qui affiche les dernières annonces disponibles pour une collection de sites directement sur la masterpage. Pour ce faire, nous utiliserons un "web custom control" ASP.NET.
II. Webpart dans une masterpage?▲
C'est en parcourant les forums que je suis tombé sur l'une ou l'autre question qui évoquait la mise en place d'un webpart dans une masterpage. Les utilisateurs ne voyaient aucune possibilité d'insérer un webpart dans une masterpage et pour cause, il n'y a généralement pas de webpart zone dans une masterpage, ce qui rend impossible l'ajout d'un webpart. On peut cependant utiliser la barre d'outils "Webparts" de Sharepoint Designer pour accéder aux différents webparts disponibles et les insérer en faisant un glisser/déplacer dans la masterpage. Ceci dit, comme expliqué dans le synopsis, on peut rencontrer certaines limitations inhérentes aux webparts de liste standard comme par exemple la liste d'annonces. On peut facilement contourner ce problème en développant un contrôle personnel ou même un webpart personnel (je préfère la première solution) que l'on déploie ensuite dans la masterpage.
III. Web custom control - Contrôle serveur web personnel, qu'est-ce que c'est au juste?▲
Une alternative (plus simple d'ailleurs) aux webparts et probablement plus adaptée au contexte d'une masterpage est le développement d'un simple contrôle serveur. Sharepoint reposant sur ASP.NET, on peut facilement développer des contrôles tel qu'on le ferait en ASP.NET pour les utiliser dans Sharepoint par la suite. Un contrôle personnel n'est autre qu'un contrôle dans lequel on implémente "manuellement" le code behind qui sera ensuite utilisé pour générer le code client interprété par le navigateur. Plutôt que de créer une page ASPX avec le support de Visual Studio, on va créer une DLL que l'on référencera ensuite dans la masterpage utilisée par notre collection de sites Sharepoint.
IV. Notre contrôle personnel dans la masterpage▲
Afin que vous ayez une idée plus précise de ce que nous allons faire, voici une capture d'écran qui montre notre contrôle inséré dans une masterpage Sharepoint. Celui-ci affiche une liste de N annonces sous forme de liens cliquables qui redirigent le visiteur vers l'annonce complète où N correspond à la valeur attribuée à la propriété ItemLimit.
V. Création du projet dans Visual Studio▲
Pour créer un web custom control en dehors du contexte d'un site web, créez simplement un projet de type class library comme illustré ci-dessous
VI. Référencement des namespaces nécessaires et héritage de la classe principale▲
Notre contrôle devant s'exécuter dans un contexte web et devant interroger une liste Sharepoint, vous devez référencer ces deux DLL
- Microsoft.Sharepoint que vous pouvez trouver dans le répertoire ISAPI de votre installation Sharepoint
- System.Web que vous trouvez directement lorsque vous ajoutez une référence à votre projet comme illustré sur l'image ci-dessous
Lorsque vous avez ajouté les DLL, veuillez référencer les espaces de noms suivants:
- Microsoft.Sharepoint
- System.Web
- System.Web.UI
- System.Web.UI.WebControls
- System.Web.UI.HtmlControls
Vous disposez à présent de tous les espaces de noms requis pour pouvoir réaliser notre contrôle. Vous n'avez plus qu'une chose à faire, c'est de faire hériter notre classe principale de WebControl car notre contrôle sera un nouveau WebControl.
VII. Propriétés de notre contrôle▲
Afin de permettre plus de souplesse et notamment pour ne pas figer des informations telles que l'URL du site Sharepoint où se trouve la liste d'annonces, le nom de la liste d'annonces, nous allons passer par des propriétés. Celles-ci permettront à l'utilisateur du contrôle de spécifier les valeurs requises. Voici deux captures d'écran qui montrent comment ces propriétés peuvent être paramétrées par l'utilisateur
Dans Sharepoint Designer
Dans un projet web classique (vous pouvez bien sûr réutiliser ce contrôle dans un projet web normal)
Voici ce que ça donne au niveau du code
bool
_TruncateTitle =
false
;
string
_SiteURL =
null
;
string
_AnnouncementList =
null
;
public
bool
TruncateTitle
{
get
{
return
_TruncateTitle;
}
set
{
_TruncateTitle =
value
;
}
}
public
string
SiteURL
{
get
{
return
_SiteURL;
}
set
{
_SiteURL =
value
;
}
}
public
string
AnnouncementList
{
get
{
return
_AnnouncementList;
}
set
{
_AnnouncementList =
value
;
}
}
///....autres propriétés
VIII. Les deux méthodes principales à réécrire▲
Comme pour un webpart, il y a certaines méthodes à réécrire pour pouvoir générer nos sous contrôles et le rendu de ceux-ci.
Méthode | Description |
---|---|
CreateChildControls | Permet de créer ses sous-contrôles (label, textbox, button etc...) |
Render | Permet de "rendre" le HTML de ces contrôles pour que le navigateur puisse les interpréter |
CreateChildControls
protected
override
void
CreateChildControls
(
)
{
ErrorMessage =
new
Label
(
);
//Holds the error message if any
ErrorMessage.
Style.
Add
(
HtmlTextWriterStyle.
Color,
"red"
);
ContentTable =
new
HtmlTable
(
);
//Will contain all the announcements
ContentTable.
Width =
"100%"
;
ContentTable.
Height =
"100%"
;
ContentTable.
Style.
Add
(
HtmlTextWriterStyle.
Overflow,
"auto"
);
HtmlTableRow HeaderRow =
new
HtmlTableRow
(
);
HtmlTableCell HeaderCell =
new
HtmlTableCell
(
);
HeaderCell.
InnerText =
Title;
//Announcement Title
HeaderRow.
Cells.
Add
(
HeaderCell);
ContentTable.
Rows.
Add
(
HeaderRow);
GetLatestAnnouncments
(
);
//Call to retrieve the announcements
this
.
Controls.
Add
(
ContentTable);
//Adding our table to the page controls
this
.
Controls.
Add
(
ErrorMessage);
//Adding our label to the page controls
}
- Nous créons un label qui affichera les messages d'erreurs en cas de problème
- Nous créons une table HTML qui contiendra toutes les annonces.
Render
protected
override
void
Render
(
HtmlTextWriter writer)
{
EnsureChildControls
(
);
//Makes sure the controls are created before rendering them
if
(
ErrorMessage.
Text ==
""
) //If no error, display the announcements
{
ContentTable.
RenderControl
(
writer);
}
else
//else display the error message
{
ErrorMessage.
RenderControl
(
writer);
}
}
- Nous appelons EnsureChildControls qui s'assure que les contrôles enfants sont bien créés.
- Nous utilisons la méthode RenderControl des contrôles pour générer le HTML.
IX. Vérifier que l'utilisateur courant ait bien un accès en lecture à la liste d'annonces▲
Une masterpage étant un objet utilisé par plusieurs sites/sous-sites, il est tout à fait possible qu'un utilisateur U ayant accès à un site S voie cette masterpage malgré le fait qu'il n'ait pas accès aux annonces que l'on met à disposition de tous. Nous devons donc vérifier au préalable si l'utilisateur courant a bien accès aux annonces ou pas et le cas échéant, ne rien afficher. Une technique permettant de le faire est la suivante:
try
{
TargetWeb.
Lists[
AnnouncementList].
CheckPermissions
(
SPBasePermissions.
ViewListItems);
}
catch
{
CanReadItems =
false
;
}
La méthode CheckPermissions lance une exception au cas où l'utilisateur courant n'a pas l'accès passé en paramètre. Ce n'est pas très élégant car il eut été préférable que cette méthode renvoie un true ou false. Donc, en cas de non accès, le code branchera le catch dans lequel vous pourrez mettre un booléen à "false". Notez qu'il est possible d'empêcher le système de générer cette exception mais dans le cas qui nous occupe, ce n'est pas nécessaire.
X. Interrogation de la liste d'annonces▲
Pour pouvoir récupérer les annonces présentes dans notre liste, nous devons bien sûr interroger celle-ci.
try
{
SPQuery AnnouncementQuery =
new
SPQuery
(
);
AnnouncementQuery.
Query =
"<OrderBy><FieldRef Name='Modified' Ascending='FALSE' /></OrderBy>"
;
AnnouncementQuery.
ViewFields =
"<FieldRef Name='LinkTitleNoMenu' /><FieldRef Name='"
+
TargetWeb.
Lists[
AnnouncementList].
Fields[
"Encoded Absolute URL"
].
InternalName +
"' />"
;
AnnouncementQuery.
RowLimit =
(
uint
)ItemLimit;
foreach
(
SPListItem AnnItm in
TargetWeb.
Lists[
AnnouncementList].
GetItems
(
AnnouncementQuery))
{
HtmlTableRow ItmRow =
new
HtmlTableRow
(
);
HtmlTableCell ItmCell =
new
HtmlTableCell
(
);
ItmCell.
InnerHtml =
"<a href='"
+
AnnItm[
"Encoded Absolute URL"
].
ToString
(
).
Substring
(
0
,
AnnItm[
"Encoded Absolute URL"
].
ToString
(
).
LastIndexOf
(
"/"
) +
1
) +
"DispForm.aspx?ID="
+
AnnItm.
ID +
"'>"
+
AnnItm[
"LinkTitleNoMenu"
].
ToString
(
) +
"</a>"
;
ItmRow.
Cells.
Add
(
ItmCell);
ContentTable.
Rows.
Add
(
ItmRow);
}
}
catch
(
Exception Ex)
{
ErrorMessage.
Text =
Ex.
Message;
}
- On crée une CAML query via la classe SPQuery en sélectionnant toutes les annonces triées ordre décroissant de leur date de création
- On dit que les champs à inclure sont LinkTitleNoMenu et Encoded Absolute URL qui représente l'URL vers l'annonce
- On dit que la limite du nombre de lignes devant être retournées correspond à la propriété ItemLimit
- On parcourt le résultat retourné par la SPQuery et on crée nos lignes/cellules de tableau permettant d'afficher l'information
XI. Déploiement de notre contrôle dans la GAC et dans Sharepoint▲
X-A. Déploiement du contrôle (la DLL) dans la GAC▲
Pour déployer la DLL dans la GAC, suivez les instructions dans ce tutoriel. La marche à suivre est identique, il est donc inutile de répéter les instructions ici.
X-B. Marquer le contrôle comme "Safe" dans Sharepoint▲
Afin que le contrôle soit reconnu comme sûr dans Sharepoint, récupérez sa signature via Reflector (également mentionné dans le lien vers le tuto ci-dessus) et ensuite éditez le web.config de votre application Sharepoint et placez-y le code suivant dans la section <SafeControls>
<SafeControl Assembly="AnnoucementBanners, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3bb84b5ba42087a0" Namespace="AnnoucementBanners" TypeName="*" Safe="True" />
X-C. Insertion du contrôle dans la masterpage Sharepoint▲
Pour éditer la masterpage, vous pouvez ouvrir Sharepoint designer, ouvrir le site de votre choix, naviguer dans "catalogs" et ensuite choisir la masterpage de votre choix. Vous pouvez également utiliser la galerie de masterpage comme illustré ci-dessous.
Ensuite, lorsque vous êtes en mode édition dans Sharepoint designer, passez en mode code et enregistrez le contrôle via une directive Register.
<%
@ Register TagPrefix=
"Announcement"
Namespace=
"AnnoucementBanners"
Assembly=
"AnnoucementBanners, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3bb84b5ba42087a0"
%>
Ensuite, à l'endroit où vous voulez afficher le contrôle, écrivez ces lignes de code
Comme vous le constatez, nous retrouvons nos propriétés AnnoucementList etc.. exposées par notre contrôle. Vous n'avez plus qu'à enregistrer les modifications apportées à la masterpage et à publier celle-ci afin que tous les visiteurs puissent bénéficier de ce contrôle. Vous pouvez tester en vous authentifiant avec des utilisateurs dont certains ont accès à la liste et pas d'autres et vous verrez que le contrôle s'adaptera en fonction du contexte.
XII. Téléchargement▲
Vous pouvez télécharger l'exemple complet décrit dans cet article ici
XIIII. Conclusion▲
Les contrôles web personnels sont une solution d'intégration non négligeable pour Sharepoint car ils incluent bien sûr du code behind et peuvent s'intégrer à la manière des webparts dans des pages, masterpage.