Kit Kai's Tech Blog

Blog about SharePoint

This Blog

Syndication

Search

Tags

News



  • Want to be notified when new posts are available? Click the icon below for more information on how to subscribe.

    Blog Flux MapStats: Stats and Counter for Kit Kai's Tech Blog Subscribe to Kit Kai's Tech Blog

    Locations of visitors to this page Add to Technorati Favorites

Community

Email Notifications

Archives

Sharepoint / CMS Blogs

MVPs', Leads' & RDs' Blogs

Singapore Usergroups

Overseas Usergroups

About Me

Central Templates Part 1

In this article, we examined how to change the default document template used by document library to create new document. However, each document library will have its own document template as SharePoint can only use documents stored in the forms folder as templates.

 

This poses a potential problem, especially when there are many document libraries using the same document template, and a new template was available requiring updating.

 

Linden Daniel, a MCS consultant currently based in Singapore were discussing how solve this problem for a client. After brainstorming, we came out with this elegant solution, which MCS later requested me to document this as the best practice for centrally manage templates.

 

 

Overview of the Solution

 

To effectively manage templates, it is recommended to use dedicated document libraries to store all the templates. Of course, the number of document library used depends on how complex your organisation is. So we will try to extend the document library properties to store the Url of the template, and override some client-side function to enable the use of those centrally managed templates.

 

 

Injecting the Steroids into the Document Library

 

As we can’t use the document library’s default template property, we have to create our own. The big problem is, we can’t use the standard .net way of inheriting classes. We also need to consider that document libraries can be saved as templates, hence we need to save the extended property into the template and retrieve it later on. So how do we achieve this? The clue is in this article. Give this some thoughts before continue reading.

 

Have you spotted the clue? Yes, make use of the Forms directory. So let’s start implementing this part of the solution.

 

First of all, we need to have a configuration form, let’s call extended document library property page. This form is just a simple asp.net webform to collect information of where to find the template. I won’t be covering how to create this form as all we needed on the form are the following webcontrols.

 

  1. A label explaining what information we are collecting.
  2. A textbox where user can specify the url of the document template.
  3. A button to save the information.

 

If you want the webform to look nicer, you can actually refer to the other pages in the layouts directory to see what controls you need to add in order to have the SharePoint look and feel.

 

The Tin Can…

 

Next, we need to save the information collected. To allow this page to be extensible, let’s store the collected information in a xml file, called config.xml. So let’s implement the Save event for the button.

 

I won’t be covering how to save the xml into the file, so let’s jump straight to saving the file in the forms directory.

 

To save or retrieve a file from the forms directory, we need to have the List object that represents the  

 

To save the file into the forms directory, the code needs to run with administrator privileges. I won’t be covering .net impersonation as there are resources out there to help you. One of them is found at http://www.15seconds.com/issue/040511.htm.

 

After impersonating the administrator, we need to open the forms directory of the document library in order to save the xml file into the forms directory. The following code shows you how to do that.

 

// Code to impersonate admin

try

{

       this._spWeb = new SPSite(SPControl.GetContextSite(System.Web.HttpContext.Current).ID).OpenWeb(SPControl.GetContextWeb(System.Web.HttpContext.Current).ID);

       this._spDocLib = this._spWeb.Lists.GetList(DocLibID, false);

       this._spForms = this._spDocLib.RootFolder.SubFolders["Forms"];

       if (this._spForms.Files["config.xml"] != null)

       {

              this._spConfigFile = this._spForms.Files["config.xml"];

       }

       // Code to undo the impersonation

}

 

 

Call in the Enforcer

 

Storing the template url in the forms directory does not change the behaviour of the new button in the document library. So we need to “teach” SharePoint to use the new url if there is one.

 

If you mouseover the “New Document” button on the toolbar, you will notice that the onclick event is invoking WPQ1createNewDocument(). Below is the original JavaScript code.

 

function WPQ1createNewDocument()

{

       var strTemplate = “http://wss/Shared Documents/Forms/template.doc”;

       var strSaveLocation = “http://wss/Shared Documents”;

       var strProgID = “SharePoint.OpenDocuments”;

       createNewDocumentWithProgID(strTemplate, makeAbsUrl(strSaveLocation), strProgID, false);

}

 

strTemplate tells the office client where to get the template, while strSaveLocation tells the office client where is the default save location. What we need to do is to override this JavaScript function whenever our template url property is defined.

 

 

Overriding the JavaScript

 

To override the script, we will be creating a class called ExtendedDocLibScripts. This class will check if our template url property is defined. Only when it is define will it then generates the script. To read the xml file in the forms directory, you need to impersonate the administrator again. Below is a snippet of the code.

 

SPWeb spWeb = new SPSite(SPControl.GetContextSite(System.Web.HttpContext.Current).ID).OpenWeb(SPControl.GetContextWeb(System.Web.HttpContext.Current).ID);

SPList spList = Microsoft.SharePoint.WebControls.SPControl.GetContextWeb(Context).GetViewFromUrl(Context.Request.Url.AbsoluteUri).ParentList;

 

DocLibExtendedConfig oDocLibExtendedConfig = new DocLibExtendedConfig(spList.ID, Context);

if (oDocLibExtendedConfig.TemplateFile != String.Empty)

{

SPFolder spFolder;

 

try

{

spFolder = spWeb.GetFolder(Context.Request.Url.PathAndQuery);

}

catch (System.Exception)

{

              spFolder = null;

}

 

       oLiteral.Text = String.Empty;

       string strSaveLocation;

       if (spFolder != null && spFolder.Exists)

       {

              string strFolderPath = String.Empty;

              strFolderPath = "/" + spFolder.Name ;

 

              while (spFolder.ParentFolder.Exists)

              {

                     spFolder = spFolder.ParentFolder;

                     strFolderPath = "/" + spFolder.Name + strFolderPath;

              }

              strSaveLocation = strFolderPath;

       }

       else

       {

              strSaveLocation = "/" + spList.RootFolder.Name;

       }

 

       oLiteral.Text += @"<script language=""Javascript"">";

       oLiteral.Text += @"function WPQ1createNewDocument()";

       oLiteral.Text += @"{";

       oLiteral.Text += @"  var strTemplate = """ + oDocLibExtendedConfig.TemplateFile + @""";";

       oLiteral.Text += @"  var strSaveLocation = """ + spWeb.Url + strSaveLocation + @""";";

       oLiteral.Text += @"  var strProgID = ""SharePoint.OpenDocuments"";";

       oLiteral.Text += @" createNewDocumentWithProgID(strTemplate, makeAbsUrl(strSaveLocation), strProgID, false);";

       oLiteral.Text += @"}";

       oLiteral.Text += @"</script>";

}

 

 

As explained above, the two important variables you need to change is strTemplate and strSaveLocation. Getting the template file is the easy part. All you need to do is to read the XML file, and assign the value to the variable. oDocLibExtendedConfig.TemplateFile is doing just what I have described above. Finding out where to save is not as straight forward, as document libraries can contain folders.

 

In the army, when we need to find out where we are, we always look for landmarks, or special land feature to pinpoint our current location. In our case, that “landmark” is the Url. Lucky for us, SharePoint API allows us to find out which folder we in are using the Url. From the SPFolder object, we then build the path to save the file to, and assign it to strSaveLocation.

 

In Part 2, we will be looking at how to piece these pieces of puzzle together.

 

 

 

Published Saturday, November 05, 2005 12:28 AM by kitkai

Comments

# Using Central Templates in SharePoint Part 1@ Sunday, November 06, 2005 2:49 PM