29 décembre 2008

Sharepoint : Provisioning de pages dans un site de publication

Dernièrement, j'ai du créer une mise en page (page layout) pour un site de publication. Toutes les pages utilisant cette mise en page contiennent les 2 mêmes webparts ainsi qu'un champ de type HTML remplie toujours de la même manière.

J'ai donc cherché à provisionner la mise en page, pour qu'à la création d'une page, les 2 webparts et le contenu HTML soient ajoutés automatiquement. Sharepoint propose une solution simple de fichier XML et de CAML, dont voici un exemple :

   1:  <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   2:      <File Url="PressWIBLayout.aspx" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE">
   3:        <Property Name="Title" Value="Press WIB Layout" />
   4:        <Property Name="MasterPageDescription" Value="PressWIBLayout" />
   5:        <Property Name="ContentType" Value="$Resources:cmscore,contenttype_pagelayout_name;" />
   6:        <Property Name="PublishingPreviewImage" Value="~SiteCollection/_catalogs/masterpage/Preview Images/SAMPLELayout.png, ~SiteCollection/_catalogs/masterpage/Preview Images/SAMPLELayout.png" />
   7:        <Property Name="PublishingAssociatedContentType" Value=";#$Resources:xxx,ContentType_Page_Title;;#0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF390064DEA0F50FC8C147B0B6EA0636C4A7D400ABEA1C761C4D4268997A1EBE2A5C8EA6;#" />
   8:        <Property Name="Footer" Value="&lt;div class=&quot;pageFooter topic&quot;&gt;&lt;p&gt;$Resources:xxx,SiteTemplate_SPS_FooterTopic;&lt;/p&gt;&lt;/div&gt;" />
   9:        <AllUsersWebPart WebPartZoneID="ZoneMainRightCol" WebPartOrder="1">
  10:          <![CDATA[
  11:  <webParts>
  12:    <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
  13:      <metaData>
  14:        <type name="XX.XXX.Runtime.Webparts.FeedBack, XX.XXX.Runtime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxx" />
  15:        <importErrorMessage>Impossible d'importer ce WebPart.</importErrorMessage>
  16:      </metaData>
  17:      <data>
  18:        <properties>
  19:          <property name="AllowClose" type="bool">True</property>
  20:          <property name="Width" type="string" />
  21:          <property name="AllowMinimize" type="bool">True</property>
  22:          <property name="AllowConnect" type="bool">True</property>
  23:          <property name="ChromeType" type="chrometype">Default</property>
  24:          <property name="TitleIconImageUrl" type="string" />
  25:          <property name="Description" type="string" />
  26:          <property name="Hidden" type="bool">False</property>
  27:          <property name="TitleUrl" type="string" />
  28:          <property name="AllowEdit" type="bool">True</property>
  29:          <property name="Height" type="string" />
  30:          <property name="MissingAssembly" type="string">Impossible d'importer ce composant WebPart.</property>
  31:          <property name="HelpUrl" type="string" />
  32:          <property name="Title" type="string">XXX:: Feed Back</property>
  33:          <property name="CatalogIconImageUrl" type="string" />
  34:          <property name="Direction" type="direction">NotSet</property>
  35:          <property name="ChromeState" type="chromestate">Normal</property>
  36:          <property name="AllowZoneChange" type="bool">True</property>
  37:          <property name="AllowHide" type="bool">True</property>
  38:          <property name="HelpMode" type="helpmode">Modeless</property>
  39:          <property name="ExportMode" type="exportmode">All</property>
  40:        </properties>
  41:      </data>
  42:    </webPart>
  43:  </webParts>          
  44:            ]]>
  45:        </AllUsersWebPart>
  46:        <AllUsersWebPart WebPartZoneID="ZoneRightTopCol" WebPartOrder="1">
  47:          <![CDATA[        
  48:  <webParts>
  49:    <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
  50:      <metaData>
  51:        <type name="XX.XXX.Runtime.Webparts.LatestWIBs, XX.XXX.Runtime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxx" />
  52:        <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
  53:      </metaData>
  54:      <data>
  55:        <properties>
  56:          <property name="Title" type="string">XXX:: latest weeks in brief</property>
  57:          <property name="WIBTitle" type="bool">False</property>
  58:          <property name="NumberOfElements" type="int">1</property>
  59:        </properties>
  60:      </data>
  61:    </webPart>
  62:  </webParts>
  63:            ]]>
  64:        </AllUsersWebPart>
  65:      </File>
  66:    </Module>
  67:  </Elements>

L'attribut Url de l'élément File spécifie la mise en page concernée et l'attribut IgnoreIfAlreadyExists=TRUE dit à Sharepoint que si la mise en page existe déjà, ce n'est pas la peine de la rajouter.

Après compilation, déploiement et activation, le résultat est impeccable : une page créée avec la mise en page ci-dessus contient bien mes 2 webparts. Cependant, je souhaitais modifier quelques propriétés dans une des 2 webparts. Je recompile, redéploie et réactive ma feature. Lorsque je recréée une page, je m'aperçois que ma page contient, non pas 2 webparts, mais 4, 2 de chaque en fait.

En faisant quelques tests, je me rends compte qu'a chaque fois que je désactive/réactive la feature, une instance pour chaque webpart spécifiée dans le module XML est ajoutée à chaque page créée avec cette mise en page. Pourtant, j'ai bien spécifié d'ignorer la mise en page si elle existe déjà dans le catalogue de la collection de site, via l'attribut IgnoreIfAlreadyExists défini à true.

En fait, la mise est bien ignorée si elle existe déjà. Malheureusement, ce n'est pas le cas des webparts spécifiées à l'intérieur. Pour moi, ceci est un bug de Sharepoint, peut-être est-il déjà référencé par Microsoft … Une autre solution de provisioning serait d'utiliser un EventReceiver ajoutant les webparts voulues à la création d'une page.

Aucun commentaire: