I’ll start out with a quote from an Microsoft MSDN Article on site definitions:
“Changing a site definition after it has already been deployed can break existing sites and is not supported. If you find that you must modify a site definition after deployment, keep in mind that adding features can cause fewer problems than changing or deleting them. Changing features often results in loss of data, and deleting features often results in broken views.”
The full article titled “Guidlines for Using Custom Site Definitions” can be found here.
Nevertheless there are plenty of scenarios that call for them, and they are not all that difficult to work with. I’ve written an article with a set of excersies that walk you through most of the basic steps you’ll need to be familiar with when creating custom site definitions.
Section 1, “Creating Site Definitions”, gives you step by step instruction on how to create a basic site definition based on the “STS” out-of-the-box definition.
Section 2, “Adding Content”, gives you step by step instructions on how to add a WSS page to your site definition (not a publishing page.) It also walks you through creating a Picture Library and an Image as part of your site definition.
Section 3, “Adding Master Pages”, gives you step by step instructions on how to include a master page in your site definition.
Not too long ago I received an urgent call from a colleague who changed the URL of her SharePoint sub-site(web) and could no longer access it. For those of you wondering how to do this; go to “site settings” and click on the “Title, Description and Icon” link; you can update the last part of the address in the Web Part Address section (you can only do this for sites, not site collections.)
It just so happens that this was a sub-site of the root, and the URL was changed to “sites”. As most of you know “sites” is automatically reserved by SharePoint for Site Collections. It is a Managed Path of type “Wildcard Inclusion”. Changing the Managed Path type to “Explicit Inclusion” will allow you to access the site, to quickly change the URL. Warning: Any Site Collections located in the Sites path will not be accessible while you are making this change. You’ll want to change it back as quickly as you can.
This is not something I would expect to happen often, I didnt think I’d hear of it again. But sure enough, a couple of weeks later I received a similar cry for help. This time a user updated the address to include “.aspx”. Dont ask me why, I didn’t bother asking. Well, this was a little more complicated (and shame on Microsoft for allowing the user to do such a thing) Now the only way to fix this (that I can think of) is via the API; luckily it doesnt mean we have to write a single line of code. While a Q-Tip and a hair pin wont help us out of this one, I have something else in my McGyver bag of tricks; SharePoint Manager to the rescue. This is an awesome tool created by Carsten Keutman, you may be familiar with one of his other tools WSPBuilder.
SharePoint Manager 2007 is a desktop application that you can run on a SharePoint Server to expose and in many cases update data of the SharePoint object model directly via the API (It gives you plenty of rope to hang yourself if you dont know what you are doing.) To fix the problem described here; run SharePoint Manager 2007, find your way to the site(web) that needs updating and select it, scroll down the properties window until you find the “ServerRelativeUrl” and change its value to something proper.
Remember to save your changes, and look, but dont touch anything else (at least not on the production server.)
- features that create workflows requiring specific groups for approvers
- features that create custom libraries or list which only specific users(groups) should be able to access
- features with custom application pages that provide specific functionality based on group membership
The list goes on and on; and while you could let the site owners create these groups and assign the necessary permissions (for most of these scenarios); wouldn’t it be safer if this was done by you. Think of all the time you’ll save on calls where you would otherwise have to explain how to do this, or troubleshooting where they’ve gone wrong. True, they’ll still have to add the users to the groups; but if they cant even do that maybe their place shouldn’t be anywhere near SharePoint.
In this posting I hope to demonstrate just how to do this by developing a feature that creates a Custom Group when activated.
We’ll begin by creating a folder called “CustomGroup” in the SharePoint feature directory (ie. “c:\program files\common files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\FEATUES\CustomGroup”)
Next we’ll create the FEATURE.xml file, it should look as follows:
Description="This Feature Creates a Custom Group"
Notice the ResourceAssembly and ReceiverClass attributes. These serve as references to the assembly that will handle the FeatureActivated, FeatureDeactivating, FeatureInstalled and FeatureUninstalling events. The PublicKeyToken of the ReceiverAssembly attribute has been set to TBD, we wont have this until we’ve created and compiled the class.
Next we’ll create the SPFeatureReceiver class referenced above. Your code should look as follows:
class FeatureReceiver : SPFeatureReceiver
public override void FeatureActivated(SPFeatureReceiverProperties properties)
//get a reference to the site collection where the feature is activated
using (SPSite site = properties.Feature.Parent as SPSite)
//get a reference to the root site / web of the site collection
using (SPWeb web = site.RootWeb)
//get a reference to a Site Owner
//(there should always be at least 1; position 0 of the
//we'll make this user the owner of the custom group
SPMember siteOwner = web.SiteAdministrators;
//prepare the group name
string grpName = "Custom Group";
//check if group exists
bool grpExists = false;
//THIS CODE SHOULD BE MOVED TO ITS OWN HELPER FUNCTION
//OR UTILITIES CLASS. IN FACT MOST OF THIS CODE NEEDS
//TO BE REFACTORED
foreach (SPGroup group in web.SiteGroups)
if (group.Name.ToLower() == grpName.ToLower())
grpExists = true;
//add the custom group to the site
//if it doesnt allready exist
web.SiteGroups.Add(grpName, siteOwner, null,
"Custom Group that I created because I can!");
//get a reference to the group we just created
SPGroup customGroup = web.SiteGroups[grpName];
//add the group to the quicklaunch
web.Properties["vti_associategroups"] + ";"
//.....FeatureDeactivating, FeatureInstalled, and FeatureUninstalling methods
The code has enough comments to be self explanatory. Make sure you create your class under the right namespace, as this is referenced in the FEATURE.xml file. You’ll also need to sign the assembly (give it a strong name), go to
for step-by-step instructions on how to do this.
Compile the assembly and add it to the GAC. While in the GAC,right click the assembly, select properties and make a note of the Public Key Token. You’ll need to update it on the FEATURE.xml file.
Deploy your feature via the Installfeature command in STSADM or by packaging it and deploying it in a WSP file.
Since we’ve set the scope of the feature to “Site”; you’ll have to activate your feature from the “Site Collection Features” link on the Site Settings page. If you are on a sub-site/web you’ll need to click on the “Go to top level site settings” link first.