Custom SharePoint Publishing Library

The MOSS publishing framework support to creating and managing publishing pages. It provides a single "pages" library to hold pages of different content types and a "create page" to create the publishing page. The create page displays the available page layouts and creates the user selected page in the "pages" library. However, there is no support for creating custom or multiple page libraries in a site.

FAQ Publishing Library:

FAQ Publishing library will be used to demonstrate the creation of custom publishing library. The FAQ publishing library contains OOTB publishing columns, article type, and keywords columns and supports scheduling of publishing pages.

Implementation

The implementation is categorized into following sections:

1. Create "FAQ Page" content type with metadata
2. Create "FAQ Layout" publishing page layout and associate with "FAQ Page" content type.
3. Create FAQ Document Library template
4. Create "FAQ Create page" to create FAQ Pages in the custom library
5. Packaging and deployment

1. Create "FAQ Page" content type.

a. Create site column definitions for article type and keywords:

<!-- FAQCTypes Feature: 12\TEMPLATE\FEATURES\FAQCTypes\Fields.xml -->
<Field ID="{5CEFB125-7D29-40ea-8897-4DEB3DD97BF2}"
Type="Choice" Name="FAQArticleType" StaticName="FAQArticleType"
DisplayName="Article Type" Group="RDA FAQ Publishing"
SourceID="http://schemas.microsoft.com/sharepoint/v3"
Required="TRUE" Format="Dropdown" FillInChoice="FALSE">
<Default></Default>
<CHOICES>
<CHOICE>Critical</CHOICE>
<CHOICE>Important</CHOICE>
<CHOICE>Informative</CHOICE>
</CHOICES>
</Field>
<Field ID="{9D28107D-F3FE-42bd-A40B-D38810E3C103}"
Type="Text" Name="FAQKeyword" StaticName="FAQKeyword"
DisplayName="FAQKeyword" Group="RDA FAQ Publishing"
SourceID="http://schemas.microsoft.com/sharepoint/v3">
</Field>


b. All publishing content type shall be inherited directly or indirectly from OOTB publishing page content type (ID: 0x010100C568DB 52D9D0A14D9B2FDCC9 6666E9F2007948 130EC3DB064 584E219954237AF39). Hence, FAQ page content type shall be inherited form publishing page as follows:


<!-- FAQCTypes Feature: 12\TEMPLATE\FEATURES\FAQCTypes\CTypes.xml -->
<ContentType
ID="0x010100C568DB 52D9D0A14D9B2FDCC9 6666E9F2007948
130EC3DB064 584E219954237AF39 0047B3EFC8307C4f 96ABF636F8A40B8D5D"
Group="RDA FAQ Publishing"
Name="FAQ Article" Description="FAQ Article Page">
<FieldRefs>
<!-- Title Column -->
<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}"
Name="Title" Required="TRUE" />

<!-- Inherited Publishing Columns Reference -->
<FieldRef ID="{9da97a8a-1da5-4a77-98d3-4bc10456e700}"
Name="Comments" />
<FieldRef ID="{51d39414-03dc-4bd0-b777-d3e20cb350f7}"
Name="PublishingStartDate"/>
<FieldRef ID="{a990e64f-faa3-49c1-aafa-885fda79de62}"
Name="PublishingExpirationDate"/>
<FieldRef ID="{aea1a4dd-0f19-417d-8721-95a1d28762ab}"
Name="PublishingContact"/>
<FieldRef ID="{61cbb965-1e04-4273-b658-eedaa662f48d}"
Name="Audience"/>
<FieldRef ID="{F55C4D88-1F2E-4ad9-AAA8-819AF4EE7EE8}"
Name="PublishingPageContent"/>
<FieldRef ID="{B3525EFE-59B5-4f0f-B1E4-6E26CB6EF6AA}"
Name="SummaryLinks"/>
<FieldRef ID="{c79dba91-e60b-400e-973d-c6d06f192720}"
Name="PublishingContactEmail"/>
<FieldRef ID="{7546ad0d-6c33-4501-b470-fb3003ca14ba}"
Name="PublishingContactName"/>
<FieldRef ID="{dc47d55f-9bf9-494a-8d5b-e619214dd19a}"
Name="PublishingContactPicture"/>
<FieldRef ID="{0f800910-b30d-4c8f-b011-8189b2297094}"
Name="PublishingPageLayout"/>
<FieldRef ID="{914fdb80-7d4f-4500-bf4c-ce46ad7484a4}"
Name="PublishingVariationGroupID"/>
<FieldRef ID="{766da693-38e5-4b1b-997f-e830b6dfcc7b}"
Name="PublishingVariationRelationshipLinkFieldID"/>
<FieldRef ID="{543BC2CF-1F30-488e-8F25-6FE3B689D9AC}"
Name="PublishingRollupImage"/>

<!-- FAQ Publishing Columns -->
<FieldRef ID="{83841BB9-85EB-4578-8BF8-E9A4CCAA89A8}"
Name="FAQArticleType"/>
<FieldRef ID="{DA92680C-442C-4e57-94A3-7AFE7C45A07B}"
Name="FAQKeyword"/>
</FieldRefs>
<DocumentTemplate
TargetName="/_layouts/RDA/FAQPublishing/CreatePage.aspx" />
</ContentType>


2. Create "FAQ Layout" publishing layout page

a. Create a publishing layout page with FAQ content type fields

<!-- 12\TEMPLATE\FEATURES\FAQCTypes\FAQLayout.xml -->
<%@ Page language="C#" Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPage,
Microsoft.SharePoint.Publishing,Version=12.0.0.0,Culture=neutral,
PublicKeyToken=71e9bce111e9429c" meta:webpartpageexpansion="full"
meta:progid="SharePoint.WebPartPage.Document" %>
<%@ Register Tagprefix="SharePointWebControls"
Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint,
Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>Title:</td>
<td><SharePointWebControls:TextField ID="TitleField"
FieldName="Title" runat="server" /></td>
</tr>
<tr>
<td>Content:</td>
<td><PublishingWebControls:RichHtmlField id="Content"
FieldName="PublishingPageContent" runat="server"/></td>
</tr>
<tr>
<td>Type:</td>
<td><SharePointWebControls:DropDownChoiceField ID="FAQArticleType"
FieldName="FAQArticleType" runat="server" /></td>
</tr>
<tr>
<td>Keyword:</td>
<td><SharePointWebControls:TextField ID="FAQKeyword"
FieldName="FAQKeyword" runat="server" /></td>
</tr>
</table>
</asp:Content>


For more information on creating and customizing page layouts, please refer to http://office.microsoft.com/en-us/sharepointdesigner/HA101741281033.aspx#3 and http://office.microsoft.com/en-us/sharepointdesigner/HA101741291033.aspx.


b. Associate FAQ page layout with content type

<!-- 12\TEMPLATE\FEATURES\FAQCTypes\FAQLayout.xml -->
<Module Name="FAQPageLayouts" Url="_catalogs/masterpage"
Path="" RootWebOnly="TRUE">
<File Url="FAQLayout.aspx" Name="FAQLayout.aspx"
Type="GhostableInLibrary">
<Property Name="Title" Value="FAQ Page" />
<Property Name="MasterPageDescription" Value="FAQ Layout Page" />
<Property Name="ContentType" Value="FAQ Page" />
<Property Name="PublishingAssociatedContentType"
Value=";#FAQ Article;#0x010100C568DB 52D9D0A14D9B2FDCC9 6666E9F2007948
130EC3DB064 584E219954237AF39 0047B3EFC8307C4f 96ABF636F8A40B8D5D;#"/>
</File>
</Module>


3. Custom Publishing Library:

a. Create FAQ publishing library template

<!-- 12\TEMPLATE\FEATURES\FAQLib\ListTemplate.xml -->
<ListTemplate Name="FAQLibrary" Type="15001"
BaseType="1" Hidden="FALSE" SecurityBits="11"
DisplayName="FAQ" Description="FAQ Pages Library"
OnQuickLaunch="TRUE" UseRootFolderForNavigation="TRUE"
FolderCreation="FALSE"
/>


b. Create a custom publishing library Schema file and include the FAQ page content type

<!-- 12\TEMPLATE\FEATURES\FAQLib\FAQLibrary\Schema.xml -->
<ContentTypes>
<ContentTypeRef ID="0x010100C568DB 52D9D0A14D9B2FDCC9
6666E9F2007948 130EC3DB064 584E219954237AF39
0047B3EFC8307C4f 96ABF636F8A40B8D5D">
<Folder TargetName="Forms/FAQPublishing" />
</ContentTypeRef>
<ContentTypeRef ID="0x0120" />
</ContentTypes>
<Fields>
<!-- all fields -->
</Fields>


4. Create Page: Create an ASPX page to create publishing pages in the custom document library. The create page shall enumerate the avaialble page layouts for the publishing library and create the publishing page with user selected page layout.


FAQ Create Page Screenshot

a. Code to enumerates the publishing pages


<!-- On page load: 12\TEMPLATE\Layouts\FAQCreatePage.aspx -->
private PageLayout[] GetPageLayoutsByContentTypeId(SPWeb web, SPContentTypeId ctId)
{
List<PageLayout> ctLayouts = new List<PageLayout>();
PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
PageLayout[] availableLayouts = publishingWeb.GetAvailablePageLayouts();

foreach (PageLayout layout in availableLayouts)
{
if (layout.AssociatedContentType.Id == ctId)
{
ctLayouts.Add(layout);
}
}
return ctLayouts.ToArray();
}


b. Code to create publishing page in the custom document library with the user selected page layout


<!-- On page create button: 12\TEMPLATE\Layouts\FAQCreatePage.aspx -->
private void CreatePage(SPWeb web, PageLayout layout,
string pageName, string pageTitle, string pageDesc)
{
string listId = this.Request.QueryString["List"];
SPList list = web.Lists[new Guid(listId)];
string fullPageName = SPUrlUtility.CombineUrl(
list.RootFolder.ServerRelativeUrl,
string.Format("{0}.aspx", pageName));

PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
PublishingPageCollection allPages = publishingWeb.GetPublishingPages();
PublishingPage newPage = allPages.Add(fullPageName, layout);

// Update Title and URL
newPage.Title = pageTitle;
newPage.Description = pageDesc;
newPage.Update();
}


5. Packaging and deployment:

a. Site scoped feature to include site columns, content types and page layout

<!-- FAQCTypes Feature: 12\TEMPLATE\FEATURES\FAQCTypes\Feature.xml -->
<Feature Id="{B5508A16-E191-448e-96AA-B101E43ED61D}"
Title="FAQ Publishing Content Types"
Description="FAQ Publishing Content Type Definitions"
Scope="Site" Version="1.0.0.0" Hidden="TRUE"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="Fields.xml" />
<ElementManifest Location="CTypes.xml" />
<ElementManifest Location="FAQLayout.xml" />
<ElementFile Location="FAQLayout.aspx"/>
</ElementManifests>
</Feature>


b. Web scoped feature to include list definition


<!-- FAQDocLib Feature: 12\TEMPLATE\FEATURES\FAQDocLib\Feature.xml -->
<Feature Id="{BA6315C2-2F1A-44b6-8E00-A5F05A19A34F}"
Title="FAQ Library" Description="FAQ Library feature"
Scope="Web" Version="1.0.0.0"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="ListTemplate.xml" />
<ElementFile Location="FAQLibrary\schema.xml"/>
</ElementManifests>
</Feature>

c. Build using WSPBuilder. For more information WSP Builder based projects, please refer to http://greggalipeau.wordpress.com/2008/05/18/developing-sharepoint-solutions-in-visual-studio/.

To enable publishing of pages, check the "Enable Item Scheduling" in library settings page. Publishing Start date and expiry date will be added to the custom library default view and the pages will be published using these date values.

Observed Issues: There were a few issues observed in the custom publishing library:

a. The summary links webpart works in edit mode, however does NOT show up in display mode. This is a possible bug in summary links webpart.

b. The Publishing page gets distorted when the page is in draft display mode. In the draft mode, the publishing toolbar user control is throwing an exception for an unknown reason (possibly a bug in the publishing toolbar control?) This can be fixed by creating a custom publishing toolbar delegate control.

3 comments:

Anonymous said...

do you have a the visual studio project files for this available? I'm trying to follow the code here, and to be honest it doesn't make much sense. Much of the XML is invalid (multiple root nodes!) so it would be great if you were able to post the code.

Wojti said...

Hi,

thank you for this great solution.

You saved me a lot of time! I realized scenario with custom page libraries.

there are some small mistakes in your code but after small fixing everything work great :)

Thank You!

Wojtek Ilowiecki

Mahesh said...

Hi Ramu,

Need quick help from you. Do you think I can conditionally change the look and feel of publishing toolbar in MOSS to only show "Submit for Approval" based on page layout (which will be based on specific content type). Basically for important types of pages, we want page to go thru approval, regardless of user's rights. User should not be able to publish directly even if user is site owner.