Now let's dig in.
If you have no experience with page layouts (and Master Pages), I suggest you read the Page Layouts and Master Pages page on MSDN. In short, page layouts allow you to customize the layout and appearance of content and web parts of pages within a MOSS publishing site. These pages are stored in a special Master Page and Page Layouts document library. Pages that are based off these Page Layouts will be stored in a 'Pages' document library at the root of the site. The nice thing about using the publishing infrastructure is that it lets you save drafts of your page revisions and does versioning and check in/out, just like a normal document library.
In order to do this tutorial, you'll need to have the MOSS Publishing Infrastructure and MOSS Publishing features turned on at the site collection and site level, respectively (under site settings).
Step 1: Start with a new STSDEV Project
You don't necessarily have to use STSDEV to create this project, however you will have to manually manipulate your Manifest.xml and .ddf files to create a SharePoint solution for deployment, as well as execute the proper commands to install/deploy etc. If you want to do without STSDEV be my guest, you'll just have to know what you're doing.
- Open Visual Studio and run STSDEV.
- Create a new project as an 'Simple Feature Solution', I'll call it 'TestPageLayout'
- Make sure you create a FeatureReceiver with this project.
- Open the 'TestPageLayout' solution once it has been created.
Step 1.5: A little more info
We're going to create a custom layout page based on a content type and deploy it with a feature. We're also going to create a feature receiver class to create a new page in our 'Pages' library based on our new Page Layout. The following steps will provide the walkthrough for doing this.
STSDEV Automatically creates the feature.xml file as well as the FeatureReceiver.cs file for you
Step 2: The feature.xml file
- Open the 'Rootfiles' folder in your solution and ensure the following directory structure exists: 'TEMPLATE\FEATURES\TestPageLayout'
- Open 'feature.xml' and add to the <ElementManifests> section the following:
<ElementManifest Location="SiteColumns.xml" />
- Next add the following to the <ActivationDependencies> node:
- There are a few key items in this file which need to be explored:
- The 'ReceiverAssembly' and 'ReceiverClass' attributes of the <Feature> element refer to the Assembly that this project will generate and the Class name of the Event Receiver class we'll working with later on.
- The <ElementManifest> and <ElementFile> elements refer to files that we will be creating in the next steps. *NOTE: If you hand-build your Manifest and .dll files (i.e. you aren't using STSDEV) you don't necessarily need the <ElementFile> referring to the .aspx page. Here's another blog post I wrote with some more information about that.
- Finally, the 'ActivationDependencies' section includes the features that need to be activated in order for this feature to work. In this case the Publishing Infrastructure feature.
- Optional: You can change the Title of the feature or the Description if you like.
- Within your 'TEMPLATE\FEATURES\TestPageLayout' directory, add a new xml file called 'SiteColumns.xml'
- Open the 'SiteColumns.xml' file, delete any existing markup and paste the following:
Group="Custom Page Column"
Group="Custom Page Column"
This file defines two columns (Fields) that we will add to the content type (in the next step).
- Within your 'TEMPLATE\FEATURES\TestPageLayout' directory, add a new xml file called 'ContentTypes.xml'
- Open the 'ContentTypes.xml' file, delete any existing markup and paste the following:
Description="Custom Home Page Template"
You should note that the FieldRef ID's value is the IDs of the Site Columns you created in the previous steps.
- In your feature directory ('TEMPLATE\FEATURES\TestPageLayout') create a 'PageLayouts' folder.
- In the 'PageLayouts' folder add an aspx page called 'CustomPageLayout.aspx'.
- Open 'CustomPageLayout.aspx', erase any existing markup and paste the following code:
<%@ Page language="C#" Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPage,Microsoft.SharePoint.Publishing,Version=184.108.40.206,Culture=neutral,PublicKeyToken=71e9bce111e9429c" meta:webpartpageexpansion="full" meta:progid="SharePoint.WebPartPage.Document" %>
<%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=220.127.116.11, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=18.104.22.168, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
<SharePointWebControls:FieldValue id="PageTitle" FieldName="Title" runat="server"/>
<asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">
<PublishingWebControls:RichImageField ID="RichImageField1" FieldName="WelcomeImage" runat="server"></PublishingWebControls:RichImageField>
<PublishingWebControls:RichHtmlField ID="RichHtmlField1" FieldName="Introduction" runat="server"></PublishingWebControls:RichHtmlField>
Notice that this page contains two PublishingWebControls that have their 'FieldName' attributes set to the values that we defined in the <FieldRef> elements of the Content Type Definition file (ContentTypes.xml).
- In the 'TEMPLATE\FEATURES\TestPageLayout' directory create a new xml file called 'Provisioning.xml'.
- Open Provisioning.xml and erase any existing markup. Then paste the following code:
<Module Name="PageTemplates" Url="_catalogs/masterpage" Path="PageLayouts" RootWebOnly="TRUE">
<File Url="CustomPageLayout.aspx" Type="GhostableInLibrary">
Value="$Resources:cmscore, contenttype_pagelayout_name;" />
Note the Property Name 'PublishingAssociatedContentType' refers to the ID of the ContentType we declared earlier.
- In the root of your solution STSDEV should have created a FeatureReceiver.cs file. Open this file
- Replace the 'FeatureActivated' method with the following code:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
using (SPSite siteCollection = properties.Feature.Parent as SPSite)
using(SPWeb web = siteCollection.RootWeb)
//Get references to the publishing site
PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
PublishingSite site = new PublishingSite(web.Site);
//ensure that the page isn't present yet (in case the feature was activated and deactivated)
if (publishingWeb.GetPublishingPages()["Pages/welcome.aspx"] == null)
//Create the default page
SPContentTypeId contentTypeID = new SPContentTypeId("0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900916CECA7C77446059633C4287903AA2A");
PageLayout layouts = publishingWeb.GetAvailablePageLayouts(contentTypeID);
PageLayout welcomePageLayout = layouts;
PublishingPage welcomePage = publishingWeb.GetPublishingPages().Add("welcome.aspx", welcomePageLayout); welcomePage.ListItem["Introduction"] = "This is some introduction default text";
//Set the default page
SPFile welcomeFile = web.GetFile(welcomePage.Url);
publishingWeb.DefaultPage = welcomeFile;
In essence, when the feature is activated, this method will create a page called 'welcome.aspx' based on the Page Layout we created. It will then make the welcome.aspx page the default page for this site.
Change your Build Configuration to BuildDeploy and build the solution.
Step 9: Test it out
If we've done everything right, we should be able to try out our feature.
- Go to the root web of your site collection and make sure the Publishing Infrastructure feature is turned on in the Site Collection Features, and that the Publishing feature is turned on in the Site Features.
- Activate the feature we created in the Site Collection features (since we scoped the feature at the 'Site' level...if we had scoped it at the 'Web' level, it would be activated from the Site Features).
- Go to the root of the site and see if everything worked correctly.
This feature should work without any problems provided your SharePoint server is configured correctly and you followed the steps outlined. If you run into errors here's a for debugging with STSDEV.