jeudi 24 septembre 2009

[MOSS/WCM/Asp.NET] Intégration d’une application Asp.NET

Ces derniers temps, je me suis penché sur l’intégration des pages/application Asp.NET dans un portail Sharepoint.
En effet, à un certain moment, l’utilisation de webparts pour une application plus poussée devient vite laborieux

Au final, j’ai relevé 3 possibilités :

  • Une page aspx dans la bibliothèque de pages d’un site
  • Une page aspx provisionnée dans le site
  • Une page aspx dans le répertoire LAYOUTS

Les contraintes :

  • Hérité de la masterpage du site web
  • Avoir un menu correspondant à mon application
  • Travailler de façon (presque) classique d’application Asp.Net

Je vais donc présenter les 3 possibilités dans un seul projet. J’utilise les templates WSPBuilder pour gagner du temps.

Etape 1 : Création du projet/solution



  • Créer un projet de type bibliothèque de classes nommé WebAppInMoss
  • Utilisation du framework 3.5
  • Ajouter les références suivantes :

image

  • Signer l’assembly (car déploiement dans le GAC)
  • Préparer l’arborescence du projet
    image


  • L’arborescence du 12 pour organiser et packager le déploiement
  • CodeBehind pour le code des pages et classes nécessaires
  • DeploymentFiles contient les batch de création de la solution et de déploiement (nous ne verrons pas ce dossier dans le détail)
  • FeatureCode pour les classes nécessaire à l’activation/installation de Features(FeautureReceiver par exemple)

Voilà, notre base est prête, nous pouvons commencer le développement de l’application.

Etape 2 : Application basique dans le LAYOUTS



  • Créer un dossier appelé WebAppTest dans le dossier LAYOUTS du projet
  • Créer une page nommé Test.aspx (sans le codeBehind)
  • Créer un fichier de configuration web.config (ce fichier nous montrera juste que Sharepoint n’est rien d’autre qu’une application asp.Net et donc l’héritage de fichier de config fonctionne)
    image
  • Ensuite, dans le dossier “Codebehind”, créer un dossier nommé “Pages” dans lequel nous mettrons le codeBehind de nos pages.
  • Dans ce dossier “Pages”, ajouter une classe nommée : Test.aspx.cs
  • A la racine du dossier “CodeBehind” , ajouter une classe nommée : BasePage.cs

image
Le fichier web.config



   1: xml version="1.0" encoding="utf-8" ?>


   2: <configuration>


   3:     <appSettings>


   4:         <add key="monTest" value="value contenu dans appSettings node"/>


   5:     appSettings>


   6: configuration>



Juste pour vérifier que ça fonctionne ;)


Le fichier Test.aspx



   1: <%@ Page Language="C#" MasterPageFile="/_layouts/application.master"


   2: AutoEventWireup="true" CodeBehind="~/CodeBehind/Pages/Test.aspx.cs"


   3: Inherits="WebAppInMoss.Pages.Test,WebAppInMoss, Version=1.0.0.0, Culture=neutral, PublicKeyToken=243730ef052a1703" %>


   4:


   5: "Content2"


   6: ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">


   7: 


   8:


   9: "Content1" ContentPlaceHolderId="PlaceHolderMain" runat="server">


  10:     toto


  11:     "server" ID="PContainer">


  12:         


  13:         "lbAddSection" runat="server">Ajoute la section au menu


  14:         "lbRemoveSection" runat="server" >Supprime la section au menu


  15:         


  16:     


  17: 



Le Inherits de notre page fait référence à notre classe Test (Test.aspx.cs) mais avec son nom fort

Par défaut, dans la propriété MasterPageFile, je mets la masterpage de Sharepoint application.master.

Or, comme nous voulons que notre page ait la même mpasterpage que notre site, la classe BasePage va nous y aider.

Le fichier BasePage.cs





   1: using System;


   2: using System.Collections.Generic;


   3: using System.Text;


   4: using System.Web.UI;


   5: using Microsoft.SharePoint;


   6: using Microsoft.SharePoint.WebControls;


   7:


   8: namespace WebAppInMoss


   9: {


  10:     /// 


  11:     /// Classe de base pour les pages contenu dans le dossier layouts


  12:     /// 


  13:     public class BasePage : Page


  14:     {


  15:         protected override void OnPreInit(EventArgs e)


  16:         {


  17:


  18:             base.OnPreInit(e);


  19:             ForceWebSiteMP();


  20:


  21:


  22:         }


  23:


  24:         /// 


  25:         /// Forece la masterPage de la page courant avec celle par défaut du website de Sharepoint


  26:         /// 


  27:         private void ForceWebSiteMP()


  28:         {


  29:             using (SPWeb currentWeb = SPControl.GetContextSite(Context).OpenWeb())


  30:             {


  31:                 this.MasterPageFile = currentWeb.MasterUrl;


  32:             }


  33:         }


  34:     }


  35: }



Ainsi au PreInit des pages héritant de cette classe, nous lui affecterons l’url du site web courant.

Le fichier Test.aspx.cs





   1: using System;


   2: using System.Collections.Generic;


   3: using System.Text;


   4: using System.Web.UI.WebControls;


   5: using Microsoft.SharePoint;


   6: using Microsoft.SharePoint.WebControls;


   7: using Microsoft.SharePoint.Navigation;


   8: using System.Web;


   9: using System.Web.UI;


  10:


  11: namespace WebAppInMoss.Pages


  12: {


  13:     public partial class Test : BasePage


  14:     {


  15:         protected Panel PContainer;


  16:         protected LinkButton lbAddSection;


  17:         protected LinkButton lbRemoveSection;


  18:


  19:         protected override void OnLoad(EventArgs e)


  20:         {


  21:             base.OnLoad(e);


  22:             EnsureChildControls();


  23:


  24:             TreeView Tree = new TreeView();


  25:


  26:             using (SPWeb currentWeb = SPControl.GetContextSite(Context).OpenWeb())


  27:             {


  28:                     SPControl.SetContextWeb(this.Context, currentWeb);


  29:                     SPSiteMapProvider MapProvider =


  30:                       (SPSiteMapProvider)SiteMap.Providers["SPSiteMapProvider"];


  31:                     SiteMapDataSource SiteData =


  32:                       new SiteMapDataSource();


  33:                     SiteData.Provider = MapProvider;


  34:                     Tree.DataSource = SiteData;


  35:                     Tree.DataBind();


  36:                 }


  37:


  38:             PContainer.Controls.Add(new LiteralControl("

Layouts

"
));


  39:             PContainer.Controls.Add(


  40:                     new LiteralControl(


  41:                            String.Format("Value de monTest (web.config) : {0}",


  42:                                          System.Configuration.ConfigurationManager.AppSettings["monTest"]


  43:                                          )


  44:                                        )


  45:                                     );


  46:             PContainer.Controls.Add(new LiteralControl("
Treeview de la collection de site"
));


  47:             PContainer.Controls.Add(Tree);


  48:


  49:


  50:


  51:


  52:


  53:         }


  54:


  55:         protected override void CreateChildControls()


  56:         {


  57:             base.CreateChildControls();


  58:


  59:             lbAddSection.Click += new EventHandler(lbAddSection_Click);


  60:             lbRemoveSection.Click += new EventHandler(lbRemoveSection_Click);


  61:


  62:         }


  63:


  64:         void lbRemoveSection_Click(object sender, EventArgs e)


  65:         {


  66:             MenuQuickLaunch.Menu.RemoveMenu(SPContext.Current.Web);


  67:         }


  68:


  69:         void lbAddSection_Click(object sender, EventArgs e)


  70:         {


  71:             MenuQuickLaunch.Menu.CreateMenu(SPContext.Current.Web);


  72:         }


  73:     }


  74: }



Les linkButton ne seront utilisé que plus tard quand nous nous attaquerons à la création d’un menu pour notre application.

L’affichage de la page nous montrera donc :



  • Les linkButtons

  • La valeur contenu dans le web.config

  • Un treeview nous montrant l’arborescence de la collection de site

Cette étape est donc terminée. Cette page est donc utilisable dans toute la collection de site avec l’url relative : _layouts/WebAppTest/Test.aspx

Etape 3 : Le provisionning de pages dans la bibliothèque “Pages” d’un site


Pour ce faire, nous allons créer une feature (nommée WebAppGhostable) qui nous permettra de déployer notre page.

Le scope de celle-ci sera Web

Voici les fichiers à créer

image

Plus une classe à ajouter dans le répertoire “CodeBehind\Pages” : GhostableInLib.aspx.cs, il s’agit bien évidemment du code-behind de la page.

Ma page GhostableInLib.aspx





   1: <%@ Page Language="C#" MasterPageFile="~masterurl/default.Master"


   2: AutoEventWireup="true" CodeBehind="~/CodeBehind/Pages/GhostableInLib.aspx.cs"


   3: Inherits="WebAppInMoss.Pages.GhostableInLib,WebAppInMoss, Version=1.0.0.0, Culture=neutral, PublicKeyToken=243730ef052a1703"


   4: meta:progid="SharePoint.WebPartPages.Document" %>


   5:


   6:


   7: <asp:Content ID="Content2"


   8: ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">


   9: asp:Content>


  10:


  11: <asp:Content ID="Content1" ContentPlaceHolderId="PlaceHolderMain" runat="server">


  12:     <asp:Panel runat="server" ID="PContainer">asp:Panel>


  13: asp:Content>



Page classique héritant de la classe GhostableInLib.aspx.cs.

La masterpage par défaut est celle du site soit : ~masterurl/default.Master
Le fichier element.xml



   1: xml version="1.0" encoding="utf-8" ?>


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


   3:     <Module Name="Pages" RootWebOnly="FALSE"


   4:     Url="Pages"


   5:     Path="Pages"


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


   7:         <File Url="GhostableInLib.aspx" Type="GhostableInLibrary"  >


   8:             <Property Name ="Title" Value="Test GhostableInLibrary"/>


   9:         File>


  10:     Module>


  11:     Elements>



Module :

  • Name : nom du module
  • Url : chemin relatif au site courant
  • Path : chemin relatif au dossier de la Feature

File :

  • Url : chemin relatif au dossier de la feature concernant le fichier. Il est combiné avec l’attribut path du module
  • Type : le fichier sera provisionné dans une bibliothèque, ici “Pages”

Le fichier Feature.xml



   1: xml version="1.0" encoding="utf-8"?>


   2: <Feature  Id="d64837bf-9af2-4b25-83c5-152cce2f40be"


   3:           Title="WebAppGhostable - Test"


   4:           Description="Test d'une application asp.net ghoster"


   5:           Version="12.0.0.0"


   6:           Hidden="FALSE"


   7:           Scope="Web"


   8:           DefaultResourceFile="core"xmlns="http://schemas.microsoft.com/sharepoint/">


   9:   <ElementManifests>


  10:     <ElementManifest Location="elements.xml"/>


  11:     <ElementFile Location="Pages\GhostableInLib.aspx"/>


  12:   ElementManifests>


  13: Feature>



La classe GhostableInLib.aspx.cs



   1: using System;


   2: using System.Collections.Generic;


   3: using System.Text;


   4: using System.Web.UI.WebControls;


   5: using Microsoft.SharePoint;


   6: using Microsoft.SharePoint.WebControls;


   7: using Microsoft.SharePoint.Navigation;


   8: using System.Web;


   9: using System.Web.UI;


  10:


  11: namespace WebAppInMoss.Pages


  12: {


  13:     public partial class GhostableInLib : Page


  14:     {


  15:         protected Panel PContainer;


  16:


  17:         protected override void OnLoad(EventArgs e)


  18:         {


  19:             base.OnLoad(e);


  20:


  21:


  22:


  23:             PContainer.Controls.Add(new LiteralControl("

GhostableInLibrary

"
));


  24:             PContainer.Controls.Add(new LiteralControl("Ceci est la page de type GhostableInLibray"));


  25:


  26:             PContainer.Controls.Add(new LiteralControl("
"
));


  27:             HyperLink hl = new HyperLink()


  28:             {


  29:                 NavigateUrl = "Ghostable.aspx",


  30:                 Text = "Lien vers la page de type Ghostable"


  31:             };


  32:


  33:             PContainer.Controls.Add(hl);


  34:             PContainer.Controls.Add(new LiteralControl("
"
));


  35:             hl = new HyperLink()


  36:             {


  37:                 NavigateUrl = String.Format("{0}/_layouts/WebAppTest/Test.aspx",


  38:                                             SPContext.Current.Web.ServerRelativeUrl),


  39:                 Text = "Lien vers la page Test du repertoire _layouts"


  40:             };


  41:


  42:             PContainer.Controls.Add(hl);


  43:


  44:         }


  45:


  46:         protected override void CreateChildControls()


  47:         {


  48:             base.CreateChildControls();


  49:


  50:         }


  51:     }


  52: }



Cette classe ajoute des liens vers la page créée précédemment dans le layouts ainsi que vers les futures pages que nous allons créer juste après.

Etape 4 : Le provisionning de pages dans le site


Pour cette étape, nous allons créer 2 autres pages en suivant le même fonctionnement que celle de l’étape 3.

L’arborescence sera donc la suivante :

image
Le fichier elements.xml modifié :



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


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


    <Module Name="Pages" RootWebOnly="FALSE"


    Url="Pages"


    Path="Pages"


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


        <File Url="GhostableInLib.aspx" Type="GhostableInLibrary"  >


            <Property Name ="Title" Value="Test GhostableInLibrary"/>


        File>


        <File Url="Ghostable.aspx"  Type="Ghostable"  >


            <Property Name ="Title" Value="Test Ghostable"/>


        File>


        <File Url="Ghostable2.aspx" Type="Ghostable"  >


            <Property Name ="Title" Value="Test Ghostable 2"/>


        File>


    Module>


    Elements>



Le fichier Feature.xml modifié :



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


<Feature  Id="d64837bf-9af2-4b25-83c5-152cce2f40be"


          Title="WebAppGhostable - Test"


          Description="Test d'une application asp.net ghoster"


          Version="12.0.0.0"


          Hidden="FALSE"


          Scope="Web"


          DefaultResourceFile="core"


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


  <ElementManifests>


    <ElementManifest Location="elements.xml"/>


    <ElementFile Location="Pages\Ghostable.aspx"/>


    <ElementFile Location="Pages\Ghostable2.aspx"/>


    <ElementFile Location="Pages\GhostableInLib.aspx"/>


  ElementManifests>


Feature>



Les pages aspx Ghostable.aspx et Ghostable2.aspx :

J’ai créé 2 pages pour montrer que l’on peut naviguer de l’une à l’autre simplement.

Les mêmes types de liens se trouvent sur la page GhostableInLib.aspx.


<%@ Page Language="C#" MasterPageFile="~masterurl/default.Master"


AutoEventWireup="true" CodeBehind="~/CodeBehind/Pages/Ghostable.aspx.cs"


Inherits="WebAppInMoss.Pages.Ghostable,WebAppInMoss, Version=1.0.0.0, Culture=neutral, PublicKeyToken=243730ef052a1703"


meta:progid="SharePoint.WebPartPages.Document" %>






<asp:Content ID="Content2"


ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">


asp:Content>




<asp:Content ID="Content1" ContentPlaceHolderId="PlaceHolderMain" runat="server">


    <asp:Panel runat="server" ID="PContainer">asp:Panel>


asp:Content>




----------------------------------------------




<%@ Page Language="C#" MasterPageFile="~masterurl/default.Master"


AutoEventWireup="true" CodeBehind="~/CodeBehind/Pages/Ghostable2.aspx.cs"


Inherits="WebAppInMoss.Pages.Ghostable2,WebAppInMoss, Version=1.0.0.0, Culture=neutral, PublicKeyToken=243730ef052a1703"


meta:progid="SharePoint.WebPartPages.Document" %>






<asp:Content ID="Content2"


ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">


asp:Content>




<asp:Content ID="Content1" ContentPlaceHolderId="PlaceHolderMain" runat="server">


    <asp:Panel runat="server" ID="PContainer">asp:Panel>


asp:Content>



Le code-behind de ces pages :

Ghostable.aspx.cs


using System;


using System.Collections.Generic;


using System.Text;


using System.Web.UI.WebControls;


using Microsoft.SharePoint;


using Microsoft.SharePoint.WebControls;


using Microsoft.SharePoint.Navigation;


using System.Web;


using System.Web.UI;




namespace WebAppInMoss.Pages


{


    public partial class Ghostable : Page


    {


        protected Panel PContainer;




        protected override void OnLoad(EventArgs e)


        {


            base.OnLoad(e);




            TreeView Tree = new TreeView();






            PContainer.Controls.Add(new LiteralControl("

Ghostable

"
));


            PContainer.Controls.Add(new LiteralControl("Ceci est la page de type Ghostable"));




            PContainer.Controls.Add(new LiteralControl("
"
));


            HyperLink hl = new HyperLink()


            {


                NavigateUrl = "GhostableInLib.aspx",


                Text = "Lien vers la page de type GhostableInLibrary"


            };




            PContainer.Controls.Add(hl);


            PContainer.Controls.Add(new LiteralControl("
"
));


            hl = new HyperLink()


            {


                NavigateUrl = "Ghostable2.aspx",


                Text = "Lien vers la page 2 de type Ghostable (elle n'apparait pas dans le menu)"


            };




            PContainer.Controls.Add(hl);


            PContainer.Controls.Add(new LiteralControl("
"
));


            hl = new HyperLink()


            {


                NavigateUrl = String.Format("{0}/_layouts/WebAppTest/Test.aspx",


                                            SPContext.Current.Web.ServerRelativeUrl),


                Text = "Lien vers la page Test du repertoire _layouts"


            };




        }




        protected override void CreateChildControls()


        {


            base.CreateChildControls();


        }


    }


}



Ghostabe2.aspx.cs


using System;


using System.Collections.Generic;


using System.Text;


using System.Web.UI.WebControls;


using Microsoft.SharePoint;


using Microsoft.SharePoint.WebControls;


using Microsoft.SharePoint.Navigation;


using System.Web;


using System.Web.UI;




namespace WebAppInMoss.Pages


{


    public partial class Ghostable2 : Page


    {


        protected Panel PContainer;




        protected override void OnLoad(EventArgs e)


        {


            base.OnLoad(e);




            TreeView Tree = new TreeView();






            PContainer.Controls.Add(new LiteralControl("

Ghostable

"
));


            PContainer.Controls.Add(new LiteralControl("Ceci est la page de type Ghostable"));




            PContainer.Controls.Add(new LiteralControl("
"
));


            HyperLink hl = new HyperLink()


            {


                NavigateUrl = "GhostableInLib.aspx",


                Text = "Lien vers la page de type GhostableInLibrary"


            };




            PContainer.Controls.Add(hl);


            PContainer.Controls.Add(new LiteralControl("
"
));


            hl = new HyperLink()


            {


                NavigateUrl = "Ghostable.aspx",


                Text = "Lien vers la page 1 de type Ghostable"


            };




            PContainer.Controls.Add(hl);


            PContainer.Controls.Add(new LiteralControl("
"
));


            hl = new HyperLink()


            {


                NavigateUrl = String.Format("{0}/_layouts/WebAppTest/Test.aspx",


                                            SPContext.Current.Web.ServerRelativeUrl),


                Text = "Lien vers la page Test du repertoire _layouts"


            };




        }




        protected override void CreateChildControls()


        {


            base.CreateChildControls();


        }


    }


}



Après déploiement les pages sont ghoster dans le site mais contrairement à l’étape 3, elles n’apparaissent pas dans la navigation.

Nous avons donc besoin d’un menu et c’est ce que nous verrons à l’étape 5.

Etape 5 : Création d’un menu à l’activation de la feature


J’ai donc décidier de créer un menu au moment de l’activation de la feature, pour ce faire, je vais donc ajouter un featureReceiver.

Dans le dossier FeatureCode, ajouter une classe nommée : WebAppGhostable.cs (en fait le nom de ma feature pour faire simple).

Voici le code :


using System;


using System.Collections.Generic;


using System.Text;


using Microsoft.SharePoint;


using Microsoft.SharePoint.Navigation;


using WebAppInMoss.MenuQuickLaunch;




namespace WebAppInMoss


{


    class WebAppGhostable : SPFeatureReceiver


    {


        public override void FeatureActivated(SPFeatureReceiverProperties properties)


        {


            SPWeb web = properties.Feature.Parent as SPWeb;




            //Instancie le menu de l'application de test


            Menu.CreateMenu(web);






        }




        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)


        {


            SPWeb web = properties.Feature.Parent as SPWeb;


            Menu.RemoveMenu(web);


        }




        public override void FeatureInstalled(SPFeatureReceiverProperties properties)


        {


            throw new Exception("The method or operation is not implemented.");


        }




        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)


        {


            throw new Exception("The method or operation is not implemented.");


        }


    }


}



NB : Les ligne concernant la création et la suppression du menu seront vu dans quelques lignes.

Voici le fichier Feature.xml modifié pour le receiver :


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


<Feature  Id="d64837bf-9af2-4b25-83c5-152cce2f40be"


          Title="WebAppGhostable - Test"


          Description="Test d'une application asp.net ghoster"


          Version="12.0.0.0"


          Hidden="FALSE"


          Scope="Web"


          DefaultResourceFile="core"


          ReceiverAssembly="WebAppInMoss, Version=1.0.0.0, Culture=neutral, PublicKeyToken=243730ef052a1703"


          ReceiverClass="WebAppInMoss.WebAppGhostable"


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


  <ElementManifests>


    <ElementManifest Location="elements.xml"/>


    <ElementFile Location="Pages\Ghostable.aspx"/>


    <ElementFile Location="Pages\Ghostable2.aspx"/>


    <ElementFile Location="Pages\GhostableInLib.aspx"/>


  ElementManifests>


Feature>



Maintenant, il ne reste plus qu’a générer un pseudo menu.

Voici les fichier à créer :

image

Et le contenu de ce menu :


using System;


using System.Collections.Generic;


using System.Linq;


using System.Text;


using Microsoft.SharePoint;


using Microsoft.SharePoint.Navigation;


using System.Web;




namespace WebAppInMoss.MenuQuickLaunch


{


    /// 


    /// Menu de l'application de test


    /// 


    public class Menu


    {


        private Menu() { }




        /// 


        /// Creer le menu de l'application


        /// 


        /// 


        public static void CreateMenu(SPWeb web)


        {


            if (web == null)


                throw new SPException("Erreur de récupération de la référence du website pendant l'activation de la feature");




            bool AllowUnSafeUpdates = web.AllowUnsafeUpdates;


            try


            {


                web.AllowUnsafeUpdates = true;


                //Menu du haut


                SPNavigationNodeCollection topNavigation = web.Navigation.TopNavigationBar;


                //menu de gauche


                SPNavigationNodeCollection quickLaunchNavigation = web.Navigation.QuickLaunch;




                //Creer les noeuds pour le menu


                SPNavigationNode sectionNode = new SPNavigationNode("Section", "Pages/Ghostable.aspx",false);


                // ajoute la section à la fin de la topNavBar


                topNavigation.AddAsLast(sectionNode);




                //ajoute la section au debut de QuickLaunch


                quickLaunchNavigation.AddAsFirst(sectionNode);






                SPNavigationNode ghostableNode = new SPNavigationNode("Test Ghostable", "Pages/Ghostable.aspx", false);


                SPNavigationNode layoutsNode = new SPNavigationNode("Test Layouts",


                                                        String.Format("{0}/_layouts/WebAppTest/Test.aspx",web.Url),


                                                        true);






                sectionNode.Children.AddAsLast(layoutsNode);


                sectionNode.Children.AddAsLast(ghostableNode);


                //sectionNode.Children.Add(layoutsNode,ghostableNode);










                web.Update();


            }


            catch (SPException ex)


            {


                throw;


            }


            finally


            {


                //on le remet à sa valeur initiale avant qu'on ne travaille dessus


                web.AllowUnsafeUpdates = AllowUnSafeUpdates;


            }


        }




        public static void RemoveMenu(SPWeb web)


        {


            if (web == null)


                throw new SPException("Erreur de récupération de la référence du website pendant l'activation de la feature");




            bool AllowUnSafeUpdates = web.AllowUnsafeUpdates;


            try


            {


                web.AllowUnsafeUpdates = true;


                //Menu du haut


                SPNavigationNodeCollection topNavigation = web.Navigation.TopNavigationBar;


                //menu de gauche


                SPNavigationNodeCollection quickLaunchNavigation = web.Navigation.QuickLaunch;




                //Supprime les noeuds créés du menu


                if(quickLaunchNavigation.Count>0)


                {


                    quickLaunchNavigation.Cast()


                                                     .Where(c => c.Title == "Section")


                                                     .FirstOrDefault()


                                                     .Delete();


                }




                if (topNavigation.Count > 0)


                {


                    topNavigation.Cast()


                                                     .Where(c => c.Title == "Section")


                                                     .FirstOrDefault()


                                                     .Delete();


                }


                web.Update();


            }


            catch (SPException ex)


            {


                throw;


            }


            finally


            {


                //on le remet à sa valeur initiale avant qu'on ne travaille dessus


                web.AllowUnsafeUpdates = AllowUnSafeUpdates;


            }


        }


    }


}



Il va donc ajouter, au moment de l’activation de lafeature, à la racine du menu du site web Sharepoint ,les liens vers le Ghostable.aspx et vers Test.aspx (page dans le LAYOUTS)

Et les supprimer à la désactivation.

Voici l’arborescence complète du projet :

image

Etape 6 : Déploiement et test de l’application


Après avoir packagé ma solution en un fichier wsp, je la déploie.

Pour mes tests, j’ai créé un sous-site de test vierge :

image

Je vais activer ma feature :

image

Et voici ma page d’accueil du Site :

image

Je peux donc me balader sur l’ensemble de mes pages grâce au menu ou aux liens qui sont dans les pages.

La page Test.aspx:

image

La page GhostableInLib.aspx :

image

La page Ghostabe.aspx:

image

La page Ghostable2.aspx:

image

Voila, ce tuto est terminé, vous avez pu remarquer que toutes les pages respectées bien la master page du site web.