What if you need to hide site templates in MOSS 2007?

Some of you might want to make only certain site templates (otherwise called site definitions like STS#0 for team site definition, STS#1 for blank site definition) available for creating sites in WSS 3 or MOSS 2007. Well, there are quite a few ways to do that. The most common and easy-to-do technique is to set the "hidden" attribute value to "true" in the WEBTEMP.xml file. Which, will no doubt, lead you into an unsupported scenario (as I always say 898631).

So what are the other options then? We can make use of "SPWebTemplateCollection" class to achieve this. It's a bit of a work though. But it will keep you in supported scenario and given that you don't want to do this on a daily (or perhaps hourly?) basis, I guess this is good enough solution. I have provided the sample code below: both to remove the available template and to re-add them if necessary.

To remove the site definitions available in a top-level site.

string myName = String.Empty;
SPSite site = new SPSite("<sharepoint server>");
SPWeb web = site.OpenWeb();
SPWebTemplateCollection templates = web.GetAvailableWebTemplates((uint)1033);
Collection<SPWebTemplate> collection = new Collection<SPWebTemplate>();
foreach (SPWebTemplate template in templates)
{
collection.Add(template);
}

foreach (SPWebTemplate template in collection)
{
if (template.Name == "BLOG#0")
{
collection.Remove(template);
break;
}
Console.WriteLine("Template name in collection: {0}",template.Name);
}
web.SetAvailableWebTemplates(collection, (uint)1033);
web.Update();

Now, for some reason if we have to get the "lost" site definition back? It's going to be tricky! Since we removed the site definition from the top-level site itself, we have no way to get a reference to the "lost" site definition just from the current top-level site's context. So now, comes the real fact! You need to have at least once site collection where "all" OOB site definitions are available in order to revert a removed site definition back. Just take a look at the following code sample that will get us the "lost" site definition and you will understand what I mean:

SPSite sourceSite = new SPSite("<url of the site where 'all' site definitions are available>");
SPWeb sourceWeb = sourceSite.OpenWeb();
SPWebTemplateCollection sourceTemplates = sourceWeb.GetAvailableWebTemplates((uint)1033);
foreach(SPWebTemplate sourceTemplate in sourceTemplates)
{
if(sourceTemplate.Name == "BLOG#0")
{
SPSite targetSite = new SPSite("<url of the site where you want to restore the removed site definition>");
                    SPWeb targetWeb = targetSite.OpenWeb();
SPWebTemplateCollection targetTemplates = targetWeb.GetAvailableWebTemplates((uint)1033);
Collection<SPWebTemplate> targetCollection = new Collection<SPWebTemplate>();
foreach(SPWebTemplate targetTemplate in targetTemplates)
{
targetCollection.Add(targetTemplate);
}
targetCollection.Add(sourceTemplate);
targetWeb.SetAvailableWebTemplates(targetCollection,(uint)1033);
targetWeb.Update();
}
}

You might think the code doesn't "look" too good. I agree it introduces unnecessary complexities for a task so simple as this. However, I do believe it is for a reason (which is unknown to me).

Hope this was helpful. So remember, whenever you need to remove/hide certain site definitions from your user's sight, DO NOT TOUCH THE WEBTEMP.XML FILE. Oh, just one more thing, I haven't had a chance to try the above in SharePoint Portal Server 2003 though. But looking at the code, I don't have a reason for it to not work there.