Saturday, March 21, 2009

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

Hi this is chakri, this is my first post, this is gather from other blog, may be it is useful somebody

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   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  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


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.

 

----------------------------------------------------------------------------------------------------------------

How to Customize (Add, Delete or Replace ) the "Site Action" menu items in Publishing site

The "Site Action" menu items in the SharePoint are rendered by the "CustomAction" feature framework. The story remains same untill the "Publishing Infrastructure Feature" is activated... When the publishing feature is activated and the site becomes SharePoint Publishing site then the datasource for the "SiteAction" menu items are rendered from the XML file which resides in 12 \ Template \ Layouts \ EditingMenu \ SiteAction.xml.

You cannot modify this "SiteAction.xml" file as it is OOB file and as well changing this file will affect the behavior in the total farm. SharePoint provides you a way to override the menu items rendered through the "SiteAction.xml" file. You can find the "Editing Menu" folder in the Master page gallery of the SharePoint publishing site, In this folder you can find the "CustomSiteAction.xml" file without the entries.

You can render your custom "Console Node" in this "CustomSiteAction.xml" to Add, Delete or replace the OOB console node links in the "Site Action" menu. Every menu item in the SiteAction.xml file has been rendered as a "ConsoleNode" class. Copy the references and the structure from the OOB "SiteAction.xml" and place it in the "CustomSiteAction.xml" file in the master page gallery. In the "ConsoleNode", you need to mention the "ConfigMenu" property to mention whether you are adding or deleting or replacing the console node in the "Site Action" menu. The enumerator value for Adding, Deleting and replacing the node are Add,Delete andReplace respectively.

Open the "CustomSiteAction.xml" file from the master page gallery. To add a console node you just need to add a "ConsoleNode" with the "ConfigMenu=Add"  entry under the structure tag of the "CustomSiteAction.xml" file. To delete and replace the existing console node from the "Site Action" menu you need to mention another property called "ChangedNodeID" to mention the node id of the OOB file which need to be deleted or replaced.

The following "CustomSiteAction.xml" file is the sample to replace the "Create Page" console node link with the custom "Create Page" link where the custom link will navigate you to the "CustomCreatePage.aspx".

 

 
   
 

 
   
ConfigMenu="Replace" ChangedNodeID="wsaCreatePage" /> 
  NavigateUrl="/_layouts/Customcreatepage.aspx" ID="wsaCreatePage1" /> 
 
 

In the above example , "ConfigeMenu" intimates that this "ConsoleNode" is replacing the OOB node "wsaCreatePage" with the new node "wsaCreatePage1" which redirects to the customcreatepage.aspx to create new publishing pages. Apart from this there are several other properties which can be set through the XML file itself such as "userRights" for permission mask etc. You can find more details about other properties here.

Save the "CustomSiteAction.xml" file in the master page gallery. Do an IISRESET and you can find your custom "Create Page" link which replaced teh OOB link and will navigate you to the "CustomCreatePage.aspx" to create the publishing pages.

You can refer more about the "ConsoleNode" and "SiteAction.xml" file in the following MSDN article.

http://msdn.microsoft.com/en-us/library/aa674506.aspx

ou can find my another blog on how to create the "CustomCreatePage.aspx" application page to store the publishing pages in various lists rather than only in Pages list.