SharePoint Rendering Templates–An Implementation

In the previous article we looked at what rendering templates were and how rendering templates work in general.  We will continue looking deeper into rendering templates and also implement a scenario which we discussed in the previous article. We will discuss the associated source code minimally so that we can devote more time into discussing the general architecture of rendering templates. That will, I hope, provide the reader with more knowledge to go ahead and build their own implementations.

The SPControlTemplateManager Class

In the end of the previous article, we discussed how rendering templates are instantiated in a container and we also briefly touched upon the SPControlTemplateManager class with a promise of looking at it a bit more deeper in this article. We will look at it now.

The SPControlTemplateManager is defined as a static class within Microsoft.SharePoint assembly under Microsoft.SharePoint.WebControls namespace. The class is not instantiated and it’s sole function is to load, cache and instantiate templates when requested by the other UI infrastructure elements within SharePoint at runtime. If you were to open up this class in Reflector, you will find a main public static method called GetTemplateByName accepting a single string parameter with the name of the template to return.

In the previous article we looked at how the default set of templates used by SharePoint infrastructure is stored within DefaultTemplates.ascx (or MobileDefaultTemplates.ascx if using mobile web browser). We also studied the structure of the file and found that each template has a specific unique ID to identify it in the grand scheme of SharePoint things. When the first request for a template with an ID comes through to SPControlTemplateManager, all the UserControl files living within CONTROLTEMPLATES folder in the SharePoint Hive are parsed and all RenderingTemplate controls are initialized and are converted to ITemplate instances and cached within an internal static Hashtable with ID being the key. We must be aware that the class doesn’t parse through the sub-folders within the CONTROLTEMPLATES folder.

After initially loading the default template files, the caching mechanism proceeds to load other .ascx files living within the folder. If it finds templates with the same name as the default one (for e.g. ListForm) then the default one is overwritten with the newly loaded one. If you were to enable “Verbose” logging for the “Web Controls” category you will see trace entries in the ULS logs that explains which template was overridden by the ones in which file. This is the technique we will be using to override a document libraries editing form with our own.

The Implementation Scenario

I think we have enough information and knowledge now to build our own little rendering template implementation. Following will be the scenario we will attempt to implement:

Metadata for documents living within any document library should not be editable when a workflow is active on the document.

The scenario is simple enough, so what options do we have to implement it? We can use:

a) Create a custom web part and add to the web part page for the library which can be built using Visual Studio and can execute code behind methods to check for workflows running for the item and disable the controls within it if one is active.

b) An ASP.NET page which does pretty much the same as described in point (a) above.

c) Use our own rendering template to override the default one and do what we described in point (a) above.

The best solution?

We will look at it one by one now to see what fits and why.

Form Web Part: SharePoint 2010 allows editing document library pages using the browser. With this option you may create a web part that provides the function of checking for workflow status and dynamically update the list form web part on the same page. This is too involved, prone to errors and is not a “clean” solution. It is not enough that the web part is created, it becomes a manual task to add this web part to all form pages for all document libraries.

ASP.NET Page: An ASP.NET page which presents the form to update the document metadata with additional functionality to check for workflow status. This is also not workable because: A lot of cumbersome code needs to be written to attach the form to all document libraries. There is also the question of how to deal with changes to the document metadata definition, such as addition, modification and deletion of fields.

Rendering Templates: This is the option we are interested in and the reason will be obvious when we implement a solution. However, let me try to list out the points that work in favour of this solution:

1) The solution is truly “plug-and-play”. The functionality is added when our solution package is deployed and removed when our solution package is uninstalled – with NO additional code to achieve it (i.e. Feature Event Receivers, PowerShell scripts and console applications etc.)

2) The solution instantly modifies all document library forms for all documents.

3) The solution is change agnostic: Adding, Modifying or Removing fields will not affect the functioning of this solution.

4) Minimal amount of coding effort required to achieve this functionality.

Building the solution

The attached demo source code contains a full working package that demonstrates what we were discussing in the rest of the article. To build the solution you will need an installation of Visual Studio 2010 with SharePoint Developer Tools installed with at least a minimal installation of SharePoint (Foundation or other version). Once built and deployed, you can see it in action by going to a document library, uploading a document and trying to edit the metadata properties of the document.

Below is a screenshot of the form when a workflow is active on the document:

form-with-workflow-running

While without a workflow the form will look and behave like any other document library form.

form-with-no-workflow-running

Solution Code Analysis

When you open up the solution code in Visual Studio 2010, you will see very few physical code files and no features or additional files. This shows how simply and elegantly we can create a complex modification to core SharePoint functions. The 2 files that we have there are:

1) DemoTemplates.ascx within CONTROLTEMPLATES folder

2) CheckWorkflowStatus.cs that defines the form component that actually does the grunt work.

If you open up DemoTemplates.ascx you will see 2 rendering templates defined:

  • DocumentLibraryForm
  • CheckWorkflowStatus

If you were to compare the DocumentLibraryForm in this file to the default implementation in DefaultTemplates.ascx, you will see only one difference – addition of CheckWorkflowStatus component in the form:

The rest of the form is derived directly from another template called “DocumentLibraryFormCore” which is defined within DefaultTemplates.ascx.

The CheckWorkflowStatus is defined as an inherited control from FormComponent. You will notice how vanilla actually the code is. The few important aspects of this component are discussed below:

The component itself uses a template called “CheckWorkflowStatus” which is defined in DemoTemplate.ascx. The template simply presents some textual information that will be displayed to the user.

The first interesting thing to note is the Visible property override. It checks whether a workflow is active and the ControlMode to make sure we are in the “Edit” form for the document. If both conditions are true then the component is visible otherwise false.

The second place of interest is the OnLoad method which again checks for an active workflow running on the item. If found it walks through the control stack for the parent web part / web control and sets the ControlMode to Display. This will make all the components on the form to read-only making it look like a “View” form – including the “Save” button which becomes invisible.

The work horse of the class is IsWorkflowActive method which checks for active workflows for the item. You will be interested to see the use of this.ListItem which is inherited from the FormComponent base class. This automatically references the currently editing item.

Conclusion

The whole experience of implementation of a rendering template based customizations for SharePoint shows how complex modifications can be performed without a lot of effort or time. I will conclude this article with the following disclaimer: This method of customisation will not be suitable for all situations. However, surgical changes required can be implemented using this method easily and without a lot of disruptive changes to the farm.

  • Brian Bedard

    You should also consider what initiates the xForm RenderingTemplate, it’s the content type. You know the XmlTemplates and FormTemplates nodes in the ContentType? So what I do is create new RenderingTemplates and the update my content types to use them. How can you guarantee your template will be loaded last and therefore be used? Try an experiment, create a RenderingTemplate with the same ID save the ASCX so it comes alphabetically before DefaultTemplates.ascx and then do it it again to come after. You’ll see something surprising. The reason DemoTemplates works is because it comes last.
    See my articles on RenderingTemplates for another perspective.http://pioneeringsharepoint.blogspot.com

    • Anonymous

      Hello Brian,

        Thanks for the comments. Although, it worked as you probably expected, it would not be prudent to assume the template files are loaded according to the name. The SPControlTemplateManager class uses Windows API to find and iterate through all .ascx files within the CONTROLTEMPLATES folder. As per Microsoft documentation, it is not guaranteed that the files will be returned in a particular order. So, I can only guess that in your case it just returned it in a specific order. More details about this can be found in: http://msdn.microsoft.com/en-us/library/07wt70x2%28v=VS.90%29.aspx.

        Please read the first part of this article series for an explanation of how templates are loaded.

  • Sergei Sergeev

    Hi Eswar Prakash!
    Thanks for interesting and informative posts, learn many new things about template rendering mechanism in sharepoint from your posts.

    • Anonymous

      Thanks for the comments, Sergei.