How to: Deploy a Page using a Feature

I am about to do start giving some training again, so I thought I would work on some more content for the blog that I could refer to people to when they are trying things out.  Today, I want to start out with the basic task of deploying a page to SharePoint.  There are actually lots of ways to get pages into SharePoint.  You can use the whole page publishing model in MOSS, but sometimes you just need a simple page with a simple web part deployed and a feature makes this task pretty easy.

For today’s example, I want to deploy a simple page with a web part or two on it.  To start, you will need to create a new folder for your feature.  You can name this whatever you want.  For the purpose of this example, we’ll call it PageTest.  Before we begin though we need a .aspx page which will host these web parts.  You can create one on your own, but I find it’s easiest to just “borrow” one from SharePoint that already exists.  A good one to borrow I have found is in the STS site template (12\TEMPLATE\SiteTemplate\STS) called default.aspx.  This .aspx page has two WebPartZones named Left and Right.  Put a copy of this file into your new feature folder.  You can customize this file however you desire, such as changing the layout or adding or subtracting WebPartZones.

By now, I am sure you probably know how to make a basic Feature.xml file, but here is one just in case.  In this case, we have a feature with a scope of Web so we’ll be deploying to an individual site.

<Feature

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

    Id="{8B486B2B-4D71-423f-BD6C-9C792299F432}"

    Scope="Web"

    Hidden="False"

    Title="PageTest"

    Description="Deploys a custom page with some web parts."

    >

  <ElementManifests>

    <ElementManifest Location="elements.xml" />

  </ElementManifests>

</Feature>

The Elements.xml file deploys files using the Module and File elements.  The Module element tells SharePoint to deploy files from a physical folder, specified in the Path attribute, to a virtual folder inside SharePoint, specified in the Url attribute.  The Path attribute is relative to the feature folder while the Url attribute is relative to the site it was deployed on.  No paths are specified in our case.

<Module Name="Pages" Path="" Url="">

The Module element can contain one or more File elements to deploy pages.  You need one File element for each page you want to deploy inside of SharePoint.  Note: that it is possible to use the same default.aspx page in your feature folder and deploy it multiple times with different web parts (i.e.: page1.aspx, page2.aspx, etc.).

<File Name="TestPage.aspx" Url="default.aspx" IgnoreIfAlreadyExists="FALSE" NavBarHome="True">

The Name attribute specifies the name the file will be called inside SharePoint.  The Url specifies the name of the file in your feature folder.  In our case, default.aspx.  The confusing part her of course being that Url in the Module element refers to the path inside SharePoint and on the File element it refers to the name of the file in your feature folder.

For each page that you can deploy, you can use CAML to automatically add web parts to the page.  To do this, you use the AllUsersWebPart element.  Remember in the page we had WebPartZones named Left and Right?  We use those same Ids here, to specify which zone to add the web part too.  The WebPartZoneOrder element specifies the order in which the web parts are added to a given zone (you can have multiple web parts in a zone and they will stack).  The definition of the web part goes inside a CDATA element inside the AllUsersWebPart element.  If you built the web part yourself, you can just paste in the XML from your .webpart file.  If you are using an out-of-the-box SharePoint web part, you can add it to an existing page and export it or go to the web part gallery and export it.  Here is what a completed file looks like with multiple web parts.

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

  <Module Name="Pages" Path="" Url="">

    <File Name="TestPage.aspx" Url="default.aspx" IgnoreIfAlreadyExists="FALSE" NavBarHome="True">

      <AllUsersWebPart WebPartZoneID="Left" WebPartOrder="1">

        <![CDATA[

          <webParts>

            <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">

              <metaData>

                <type name="MyWebPart.TestWebPart, MyWebPart, Version=1.0.0.0, Culture=neutral" />

                <importErrorMessage>Cannot import this Web Part.</importErrorMessage>

              </metaData>

              <data>

                <properties>

                  <property name="Title" type="string">My Web Part</property>

                  <property name="Description" type="string">A test web part.</property>

                </properties>

              </data>

            </webPart>

          </webParts>

        ]]>

      </AllUsersWebPart>

      <AllUsersWebPart WebPartZoneID="Left" WebPartOrder="2">

        <![CDATA[

        <WebPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/WebPart/v2">

          <Title>Search Box</Title>

          <Description>Used to search document and items.</Description>

          <MissingAssembly>Cannot import this Web Part.</MissingAssembly>

          <Assembly>Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>

          <TypeName>Microsoft.SharePoint.Portal.WebControls.SearchBoxEx</TypeName>

          <GoImageUrl xmlns="urn:schemas-microsoft-com:SearchBoxEx">/_layouts/images/gosearch.gif</GoImageUrl>

          <GoImageUrlRTL xmlns="urn:schemas-microsoft-com:SearchBoxEx">/_layouts/images/goRTL.gif</GoImageUrlRTL>

          <GoImageActiveUrl xmlns="urn:schemas-microsoft-com:SearchBoxEx">/_layouts/images/gosearch.gif</GoImageActiveUrl>

          <GoImageActiveUrlRTL xmlns="urn:schemas-microsoft-com:SearchBoxEx">/_layouts/images/goRTL.gif</GoImageActiveUrlRTL>

          <DropDownModeEx xmlns="urn:schemas-microsoft-com:SearchBoxEx">ShowDD</DropDownModeEx>

          <ScopeDisplayGroupName xmlns="urn:schemas-microsoft-com:SearchBoxEx">Search Dropdown</ScopeDisplayGroupName>

          <RegisterStyles xmlns="urn:schemas-microsoft-com:SearchBoxEx">true</RegisterStyles>

          <ShouldTakeFocusIfEmpty xmlns="urn:schemas-microsoft-com:SearchBoxEx">false</ShouldTakeFocusIfEmpty>

        </WebPart>

        ]]>

      </AllUsersWebPart>

      <AllUsersWebPart WebPartZoneID="Right" WebPartOrder="1">

        <![CDATA[

                   <WebPart xmlns="http://schemas.microsoft.com/WebPart/v2" xmlns:iwp="http://schemas.microsoft.com/WebPart/v2/Image">

                        <Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>

                        <TypeName>Microsoft.SharePoint.WebPartPages.ImageWebPart</TypeName>

                        <FrameType>None</FrameType>

                        <Title>$Resources:wp_SiteImage;</Title>

                        <iwp:ImageLink>/_layouts/images/homepage.gif</iwp:ImageLink>

                        <iwp:AlternativeText>$Resources:core,sitelogo_wss;</iwp:AlternativeText>

                   </WebPart>

                   ]]>

      </AllUsersWebPart>

    </File>

  </Module>

</Elements>

When SharePoint is deploying the page, it combines your .aspx page with what is in the elements.xml file to output the completed page.  At this point you are ready to install and activate your feature.  You can put this in a solution package at this point to ease deployment.  When you activate the feature, you should get something that looks like this.

FileDeployment

Of course, deactivating the feature won’t remove this page or its web parts.  However, you can always easily implement a feature receiver to cleanup the files you deployed.  This is how you deploy simple pages using CAML.  This is effectively the same way that Site Templates deploy pages as well (except the web parts and views are defined in onet.xml instead).

© 2008 SYS-CON Media