Why should 'one' always save publishing pages in "Pages" list in MOSS !!! Bend It !!!!

The Approval Workflows, Content Management, Authoring all are fair enough for the publishing pages in MOSS. But why should you store the publishing web pages only in the inbuilt "Pages" list when you can have any number of lists enabled with "Page Content Type".

The "Create Page" link from the "Site Action" menu will land you in the "CreatePage.aspx" under layouts directory. You can find the "Pages" list has been hardcoded there as the destination library. Any publishing page you create from the "CreatePage.aspx" will be stored in the "Pages" library. In my support profession i found many of the users wants to bend this behavior of SharePoint and wants to store the publishing pages in varios libraries based on the category. To achieve this either they create individual web application or an extended application under the layouts directory which makes them frustrated due to large development work and sometimes leads to the unsuccessfull attempt because of the limitations in the usage of high secured SharePoint API's outside the SharePoint context.

I don't want to break rules but following them is not really my cup of tea.... So how we can make the other libraries which are enabled with "Page content Type" to be available in the "CreatePage.aspx" and store the publishing pages in the selected library... (You cannot store publishing pages without the page content type enabled with the document library or List !! )

1. Create custom "CreatePage.aspx" - as i already told i don't want to break the rules by modifying the OOB CreatePage.aspx.

2. Modify the "Site Action" menu to navigate to the "Custom Createpage.aspx" to create publishing page - again do it without bending the rules.

Creating the custom createpage.aspx involves the implmentation of following few steps :

a. Copy the "CreatePage.aspx" and place it under the layouts with some custom name , say "CustomCreatepage.aspx"

b. In the "CustomCreatePage.aspx" find the Label  <asp:Label ID="parentUrlLabel" runat="server" /> and make the visible property of this label to "False". This is the label where the "Pages" list is hard coded. Don't remove the label from the page as this label reference has been used in the code behind class and will result in Null reference error while creating the page.

c. Add a dropdownlist control <asp:DropDownList ID="ddlDocLib" runat="server"></asp:DropDownList> in the "CustomCreatePage.aspx" after the above said label control.

d. You might be thinking about writing the code behind and compiling a DLL for this custom page but it's not possible as this page already inherits Microsoft.SharePoint.Publishing.Internal.CodeBehind.CreatePagePage class from the Microsoft.SharePoint.Publishing Assembly. There are several methods from this class has been called in the server scripting of this page which makes you to stick to the inheritance of this class for the page directive.

e. Add a server script in the page (In line coding,Wow ASP.NET !!) and override the onload event to populate the dropdownlist with the page content type enabled Lists. The following is the code snippet for the onload event in the server script of the"CustomCreatePage.aspx"

protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        ddlDocLib.Items.Add("--Select Destination List--");
        SPWeb web = SPContext.Current.Web;
        SPListCollection lists = web.Lists;
        foreach (SPList list in lists)
        {
            SPContentType _cType = list.ContentTypes["Page"];
            if(_cType != null)
            {
                  ddlDocLib.Items.Add(new ListItem(list.Title, list.ID.ToString())); 
             }
        }
    }

f. Next step is to override the code behind of the create button. Write a server script for the button click event in the "CustomCreatePage.aspx" as follows. We will be using the selected list in the DropDownlist as teh destination library to store the publishing pages.

protected void OnCustomSubmit(Object sender, EventArgs e)
    {
       
         string newPageUrl = "";
         SPWeb web = SPContext.Current.Web;
         PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
         PageLayout[] layouts = publishingWeb.GetAvailablePageLayouts();
        
         int layoutItemId = Convert.ToInt32(pageTemplatePicker.SelectedValue);
       
         PageLayout layout = FindLayoutById(layoutItemId,publishingWeb);

         string pageName = urlNameTextBox.Text + ".aspx";
        
         PublishingPage newPage = publishingWeb.GetPublishingPages().Add(ddlDocLib.SelectedItem + "/" + pageName, layout);
         newPageUrl = web.Url + "/" + newPage.Url; // Here you can append the Querystring if you want to show the created page in the Edit Mode.
         
         newPage.Title = titleTextBox.Text;

         newPage.Description = descriptionTextBox.Text;

         newPage.Update();
         Response.Redirect(newPageUrl);

  }

The FindLayoutById method used in the above click event :

protected PageLayout FindLayoutById(int layoutItemId,PublishingWeb localPublishingweb)
    {
    SPListItem itemById = localPublishingweb.Web.Site.RootWeb.GetCatalog(SPListTemplateType.MasterPageCatalog).Items.GetItemById(layoutItemId);
    if (itemById == null)
    {
        return null;
    }
    return new PageLayout(itemById);
    }

f. Finally Change the Serverclick property of the create page button to the custom button click event created above as follows

<asp:Button runat="server" class="ms-ButtonHeightWidth" OnClick="OnCustomSubmit" Text="<%$Resources:cms, createpage_createbutton%>" id="buttonCreatePage" AccessKey="<%$Resources:cms,createbutton_accesskey%>"/>

g. Save the "CustomCreatePage.aspx"

UFFFF.... The "CustomCreatePage.aspx" is ready to rock !!!!

Now we need to modify the "Site Action" menu behavior so that it will land you in the "CustomCreatePage.aspx" to create the publishing pages. Click HERE to know that how to replace the OOB "Create Page" link with your custom create page link in the "Site Action".

Once you replaced the console node link for the "CustomCreatePage.aspx" in the "Site Action" then the customization is complete to bend the behavior of publishing page storage in MOSS publishing site. Now you can store the publishing pages in any of the list in your sharepoint site which are enabled with the Page content type.

                                                                                 HAPPY CUSTOMIZING !!!

 

CustomCreatePage.zip

Comments

  • Anonymous
    July 17, 2008
    PingBack from http://blog.a-foton.ru/2008/07/why-should-one-always-save-publishing-pages-in-pages-list-in-moss-bend-it/

  • Anonymous
    July 17, 2008
    The "Site Action" menu items in the SharePoint are rendered by the "CustomAction" feature framework.

  • Anonymous
    July 30, 2008
    Hi.  Please help - I followed all the steps given in your article, including the second article of replacing the create page link, and I keep getting this: Error: Unknown Error(on the Customcreatepage.aspx).  Any ideas?  Any help is appreciated.    

  • Anonymous
    July 31, 2008
    Ellay, To see the stack trace of the error message make the customerror mode to off and the callstack to true in the web.config. Please let me know teh elobarated error message

  • Anonymous
    September 01, 2008
    Hi, this is a great article just what i was after. The only i error i had when using the cope from the page was that you forgot to mention the namespace import that is needed. <%@ Import Namespace="Microsoft.SharePoint.Publishing" %> otherwise PublishingWeb etc are a not regonised. Thanks a lot for this article.

  • Anonymous
    September 02, 2008
    Thanks for notifying this Kwakker. Its really good that it helps you out.

  • Anonymous
    April 27, 2009
    In this solution we can create pages just in subfolders of Pages folder... I modified it a little bit: in OnLoad method: ddlDocLib.Items.Add(new ListItem(list.Title, list.RootFolder.Name)); in OnCustomSubmit method: PublishingPage newPage = publishingWeb.GetPublishingPages().Add(web.Url + "/" + ddlDocLib.SelectedItem.Value + "/" + pageName, layout); Now, you can store publishing pages with the page content type enabled with the document library or List.

  • Anonymous
    April 28, 2009
    Hi, Please answer me if you here me, I done what you explained and every thing is great, Thanks tooo much. But I Want to use this custom page when I create a new page from the menu in the Document Library I want to create the page in. Is there a way to do this. Thanks tooooo much.

  • Anonymous
    June 05, 2009
    Hi Net, Create a custom content type and mention the TargetName attribute of the DocumentTemplate element in the custom content type to the custom "CreatePage.aspx". Now attach the Content type to the documnet libraray and it will navigate you to create the pages to teh custom page.

  • Anonymous
    June 05, 2009
    Hi Di_mon, This solution itself targetting any Doc Lib or List (enabled with page content type) to store the pages.

  • Syed.
  • Anonymous
    July 09, 2009
    Hi Syed, Thanks for the article. If we save publishing pages into other document libraries, it seems that the "Page Settings" options becomes no longer available for the page. do you have any suggestion / solution on how to resolve this? Cheers, pit

  • Anonymous
    August 14, 2009
    Hi Pit, The 'Page Settings' menu item disappears because it has HideStates='IsPublishingPageFalse' in EditingMenu.xml. It looks like SharePoint determines this value by looking at the document library name. Yeu can work around this by either modifying EditingMenu.xml (not recommended), or by creating CustomEditingMenu.xml and modifying the menu there. Hope this helps! Syed, Thanks for posting this excellent article. Having read various posts on the subject suggesting that it was impossible I was about to give up all hope!

  • Anonymous
    November 16, 2009
    Hi, I have created another drop down list called ddlDocLib_Sub in which i want to display the sub folder based on the previous list (ddlDocLib) how do i do this

  • Anonymous
    July 07, 2010
    The comment has been removed

  • Anonymous
    October 31, 2011
    The comment has been removed

  • Anonymous
    May 30, 2014
    The comment has been removed

  • Anonymous
    January 27, 2015
    ThankYou, but i had to Import the Microsoft.SharePoint.Publishing namespace