Custom wiki site definition with custom document template for creating wiki pages

Architectural behavior of wiki site definition and the wiki page library

1. When a site is created based on the OOB wiki site definition, a wiki page library (List Template Type = 119) instance is created which is attached with the wiki document content type. Following is the snippet from the Onet.xml which explains you the remaining

<Lists>

<List FeatureId="00BFEA71-C796-4402-9F2F-0EB9A6E71B18" Type="119" Title="$Resources:core,WikiWebLibPages;" Url="$Resources:core,WikiWebLibPages_Folder;" VersioningEnabled="TRUE" />

</Lists>

2. You can find the wiki document content type details in the OOB “ctypes” feature. The wiki content type has the document template pointing to the “CreateWebpage.aspx” application page. So whenever you create a new item (wiki page) in the wiki page library it will navigate you to the “Createwebpage.aspx” where you can fill the wiki field and create the wiki page.

<DocumentTemplate TargetName="/_layouts/CreateWebPage.aspx" />

Another thing you need to notice in the wiki document content type is the “Wiki Field”. This content type has the site column called “Wiki field” which is of “Multiple lines of text” field type with RichTextMode enabled. This is the field where one can enter the wiki content and create wiki pages.

<FieldRef ID="{c33527b4-d920-4587-b791-45024d00068a}" Name="WikiField" />

3. Wiki page library is basically a document library based and we need to add the items as a files in the wiki page library. To explore this truth more you can investigate the button click code behind of “CreateWebpage.aspx”. This event basically calls the overloaded “Add” method of SPFileCollection class to create the wiki page in the wiki pages library. There are several overloaded “Add” method available with SPFileCollection class among them the following “Add” method is called to create wiki pages.

public SPFile Add(string urlOfFile, SPTemplateFileType templateFileType)

{

string str;

switch (templateFileType)

{

case SPTemplateFileType.StandardPage:

str = @"pages\viewpage.aspx";

break;

case SPTemplateFileType.WikiPage:

str = @"DocumentTemplates\wkpstd.aspx";

break;

default:

throw new ArgumentException();

}

return this.AddGhosted(str, urlOfFile);

}

4. From the above snippet you can find that if the page created is wiki page then it will be created based on the “wkpstd.aspx” layout which is available under the DocumentTemplates folder of 12 hive. This page has been hard coded in the “Add” method of SPFileCollection.

I had worked on a requirement where in I want to change the layout (wkpstd.aspx) of the wiki pages based on the business requirement.

I have created the own layout based on the OOB wkpstd.aspx and placed it under the DocumentTemplates folder. So the custom layout is created successfully and available for creating wiki pages.

OOPS !! But very unlikely the OOB wkpstd.aspx page is hard coded as mentioned above in the “Add” method of SPFileCollection class. So even if you create a custom layout for creating wiki pages the “CreateWebPage.aspx” is going to use the OOB wkpstd.aspx to create the wiki pages.

Now let’s see how to workaround this by design behavior of SharePoint with some customization technique. This walkthrough will help us understand the steps to follow when we start customizing/ bending some behavior of SharePoint.

1. First we need to change the code behind of “CreateWebPage.aspx” so that we can avoid using the OOB “wkpastd.aspx” to create wiki pages.

2. Modifying the OOB pages are not supported so we need to copy the OOB “CreateWebPage.aspx” and need to override the button click event in the custom “CreateWebpage.aspx”.

3. Need to create a custom content type inheriting from OOB wiki document content type which will have the custom “CreateWebpage.aspx” as the document template.

4. Attach the custom content type with the wiki pages library and detach the OOB wiki document content type.

5. So now when you are going to create wiki page from wiki pages library then you will be navigated to the custom “CreateWebPage.aspx” page which will use the custom “wkpstad.aspx” as a template to create the wiki pages.

Step 1 : Creating custom “CreateWebpage.aspx” and overriding the Code behind for creating the wiki pages based on the custom “wkpastd.aspx”

From the above explanation it’s sure that we cannot use the “Add” method of SPFileCollection. But we need to use any of the overloaded “Add” method to add a wiki page as a file to the wiki page library. So the only work around which seems to be possible for me is as follows :

a. Provision the default wiki pages for the wiki site based on the custom “wkpastd.aspx” during the site creation through “Onet.xml”. You can achieve this by creating a custom wiki site definition and making the changes to the Onet.xml of the custom wiki site definition.

<Module Name="DefaultWikiPages" List="119" Url="$Resources:core,WikiWebLibPages_Folder;" Path="" SetupPath="DocumentTemplates">

<File Url="Customwkpstd.aspx" Name="$Resources:core,nav_Home;.aspx" Type="GhostableInLibrary">

<Property Name="WikiField" Value="$Resources:core,WikiHomeContent;" />

<NavBarPage Name="$Resources:core,nav_Home;" ID="1002" Position="Start" />

<NavBarPage Name="$Resources:core,nav_Home;" ID="1010" Position="Start" />

</File>

<File Url="Customwkpstd.aspx" Name="$Resources:core,nav_HowToUseThisWikiSite;.aspx" Type="GhostableInLibrary">

<Property Name="WikiField" Value="$Resources:core,WikiHowToUseContent_Part1;$Resources:core,WikiHowToUseContent_Part2;$Resources:core,WikiHowToUseContent_Part3;$Resources:core,WikiHowToUseContent_Part4;$Resources:core,WikiHowToUseContent_Part5;$Resources:core,WikiHowToUseContent_Part6;$Resources:core,WikiHowToUseContent_Part7;$Resources:core,WikiHowToUseContent_Part8;" />

<NavBarPage Name="$Resources:core,nav_HowToUseThisWikiSite;" ID="1010" />

</File>

</Module>

b. So these pages now will be successfully created based on the custom “wkpastd.aspx” template. Now get the byte array of this page in the wiki pages library and pass it to the overloaded “Add” method of SPFileCollection to add the wiki page into the wiki pages library.

You can use the code sample given below in the code behind of button click Event in your custom "CreateWebPage.aspx"

SPWeb oWeb = SPContext.Current.Web;

SPList oList = oWeb.Lists["Wiki Pages"];

SPFileCollection oFiles = oList.RootFolder.Files;

SPFile oFile = oFiles[0];//getting the home page to collect the byte array of the custom document template

byte[] oByte = oFile.OpenBinary();

SPFile oFile1 = oFiles.Add(oList.RootFolder + "/TestWiki.aspx", oByte);

SPListItem oItem = oFile1.Item;

oItem["Name"] = "Test";

oItem["WikiField"] = Name.Text;// (Name is the ID of the textbox. Get the wiki content from the Rich textbox of the CreateWebPage.aspx

oItem.Update();

Step 2: Creating custom content type inheriting from OOB wiki document content type.

a. Create a custom feature to create a custom content type inherited from the OOB wiki content type. You can get the content type ID of OOB wiki document content type from the OOB “ctypes” feature.

b. You can install this custom feature and can include this feature in the “Site Features” of the Onet.xml so that this feature will get activated by default when the site is created based on this custom wiki site definition.

Step 3: Attaching the custom content type and detaching the OOB wiki content type from the wiki pages library

Create a feature event receiver for the custom content type feature and in the feature activated event attach the custom content type to the wiki pages library and detach the OOB wiki content type from the wiki pages library.

Now the custom wiki site definition with all the customization is ready for the use. Now create a site based on the custom wiki site definition and you can find some default pages created based on the custom “wkpastd.aspx” in the wiki pages library. The custom content type will be attached with the wiki pages library and you will be navigated to the custom “CreateWebPage.aspx” for creating wiki pages where you have already implemented the logic to create the wiki pages based on the custom “wkpstd.aspx”.