Introduction
As I have ever written several time in my previous posts, one of the severe limitation of SharePoint Foundation is that the Wiki Pages are based on a single template wkpstd.aspx located at
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\DocumentTemplates
If you try to add a wiki page programmatically to a wiki page library of a SharePoint Foundation team site and you want it to be ghosted you must use the method SPFileCollection.Add with this signature :
Add(String, SPTemplateFileType)
And pass the reference of the wiki page template wkpstd.aspx to the SPTemplate parameter. If you use any other signature, you will be able to add a wikipage, but it will be unghosted.
I am now going to show you a very amazing workaround to use another template than the wkpstd.aspx one and will process in two steps. First I will demonstrate it so as you can easily understand its principle then I will provide a programmatic way of doing it.
Demonstration
Start creating your new template by duplicating the wkpstd.aspx and rename it wkpcustom.aspx, then perform a little operation of customization in order each page based on this new template can tell its name :
In the page directive section add the namespace System.Diagnostics because the wiki pages will tell their nam in the debugView...
<%@ Import Namespace="System.Diagnostics" %>
Then, at the top of the PlaceHolderMain section paste this code:
protected override void OnPreInit(EventArgs e){
base.OnPreInit(e);
Debug.WriteLine(SPContext.Current.File.Name);
}
Then, we are going to prepare a feature to reference this wkpcustom.aspx file in a SharePoint Foundation wiki page library.
Assume we call the feature
Provisioning.SPF_WikiPages
Here is the feature.xml code:
<?xml version="1.0"
encoding="utf-8"?>
<Feature Id="00BFEA71-2062-426C-90BF-714C59600AAA"
Title="Adding pre populate wiki
pages"
Description="This feature will add pre-populate wiki
pages to the site pages wiki library of this site"
Version="1.0.0.0"
Scope="Web"
Hidden="false"
DefaultResourceFile="core"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest
Location="elements.xml"
/>
</ElementManifests>
</Feature>
And this is the xml code of the elements.xml file
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Url="SitePages" >
<File Url="wkpcustom.aspx" Type="GhostableInLibrary"></File>
</Module>
</Elements>
Last, a screen shot of the Provisioning.SPF_WikiPages feature folder
Then, install the feature and activate it for one of the team site of your Farm and you will have a reference to your page in the site pages library of this team site.
You can see a reference to the wkpcustom file located in the feature folder on the server
And because this file was provisioned by a feature, although there is in line code in it, if you display the wiki page using this file, it will work, the code will run and will write the name of the page in the debugview.
But, wait a minute, this file is already a template. It is a template for just one page within the site pages library but it is exactly like the wkpstd.aspx for the other pages. So assume we could have several pages within the library based on this file we would have created a new template. I see some of you smiling...
You have understood... It is what we are going to do now...
Now
is the time to use another workaround I have already shown in a previous post to
open our library in explorer mode.
So switch to shared documents library,
open it in explorer mode, then using the explorer folder navigation go back to
the site pages library but in explorer mode now
Then rename the page in "page 01.aspx"
then go back to the site pages library within the SharePoint UI. You will notice that the page is renamed and if you displayed it, its name in the debugview has changed too. While renamed, the page remains in its ghosted state and linked to the "template".
Now deactivate the feature, then reactivate it and you will have a new page wkpcustom.aspx beside the "page 01.aspx" and the two pages are linked to the same file on the server, so if we display one then the other, debugview will trace the two names based on the code of an unique file on the server: we have created our first custom template for a wiki page library in SharePoint Foundation!
Now we have done the demonstration we just have to find the way to do it programmatically:
Coding the sequence
this applicative page called from your site will provision 9 pages in your site page library pointing on the same unique template wkpcustom.aspx located in the feature folder. If you modify the file in the folder, you will modify the 9 pages
<%@ Page Language="C#" AutoEventWireup="true" Inherits="Microsoft.SharePoint.WebControls.LayoutsPageBase"
DynamicMasterPageFile="~masterurl/default.master" %>
<%@ Assembly Name="System.Core,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.Administration" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Linq" %>
<%@ Assembly Name="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<asp:content id="PageHead" contentplaceholderid="PlaceHolderAdditionalPageHead" runat="server">
</asp:content>
<asp:content id="Main" contentplaceholderid="PlaceHolderMain" runat="server">
<script language="C#" runat="server">
protected override
void OnLoad(EventArgs e)
{
base.OnLoad(e);
SPWeb myWeb = SPContext.Current.Web;
myWeb.AllowUnsafeUpdates = true;
for (int i = 1; i < 10; i++)
{
if (myWeb.Features[new Guid("{00BFEA71-2062-426C-90BF-714C59600AAA}")] !=
null)
{
myWeb.Features.Remove(new Guid("{00BFEA71-2062-426C-90BF-714C59600AAA}"));
}
myWeb.Features.Add(new Guid("{00BFEA71-2062-426C-90BF-714C59600AAA}"));
SPList myList = myWeb.Lists["Site
Pages"];
SPListItem myItem = null;
SPContext.Current.Web.AllowUnsafeUpdates = true;
foreach (SPListItem anItem in myList.Items)
{
if (anItem.Name == "wkpcustom.aspx")
{
myItem = anItem;
}
}
string destinationUrl = myWeb.Url +
"/" + myList.RootFolder.Url + "/" + "Wiki_page0" + i + ".aspx";
myItem.File.MoveTo(destinationUrl);
myItem.File.Update();
myWeb.Features.Remove(new Guid("{00BFEA71-2062-426C-90BF-714C59600AAA}"));
}
lbl1.Text = "Your files has been
provisionned successfully...";
}
</script>
<asp:Label runat="server" ID="lbl1" ></asp:Label>
</asp:content>
<asp:content id="PageTitle" contentplaceholderid="PlaceHolderPageTitle" runat="server">
Provisioning Team Site Wiki Pages
</asp:content>
<asp:content id="PageTitleInTitleArea" contentplaceholderid="PlaceHolderPageTitleInTitleArea"
runat="server">
Provisioning Team Site Wiki Pages
</asp:content>
Here are the screen shots of the applicative page after its provisioning job is finished
and the site pages library with the 9 new pages
And if I call the 9 pages, each of them will tell me its name.
And now, I have changed the instruction of the name displaying in the template, and I have called back the 9 pages and here is the result.
Have a lot of fun with that!