Sunday, 5 August 2007

Creating, deploying and updating custom site definitions

This is the first article in a series of three where we'll discuss custom site definitions, and in particular how to run your own custom code in the site creation process. This technique is useful if you need to make any customizations using the API beyond what can normally be accomplished with a site definition. In my series (for the full series contents, see my introduction at http://sharepointnutsandbolts.blogspot.com/2007/07/article-series-custom-permissions-with.html), I use the example of creating a site definition with specific security permissions 'attached' - so that when any sites are created using the definition, specific permissions are applied which are different to those of the parent site (this is unlike the default, which is for new sites to inherit the parent site's permissions). More background can be found in the introductory article linked to earlier.

In this article we'll start with the site definition basics - I'll also supply the set of files used in this article in a link at the end. Fundamentally, a custom site definition is a template from which new SharePoint sites can be created. Customizations can be packaged into the definition, so that they are present automatically in sites created from the template. Consider the following about site definitions:

  • they are created by copying an existing (e.g. out-of-the-box) site definition and adding customizations
  • XML files (in particular the onet.xml file) specify what a site definition consist of (i.e. .aspx pages, images, web parts, functionality [in the form of SharePoint Features])
  • they provide a similar functionality to site templates (.stp files) - for a discussion of the differences between site definitions and site templates see http://msdn2.microsoft.com/en-us/library/aa979683.aspx
  • site definitions can be deployed using a SharePoint Solution package (.wsp file), so that files do not need to be manually copied to each web server in a SharePoint farm

The process for creating site definitions is well-documented in the WSS 3.0 SDK at http://msdn2.microsoft.com/en-us/library/ms454677.aspx, so I actually won't cover it here but would encourage you to follow the link. However I will quickly run through some of the key elements in the onet.xml file to go over what can be done with site definitions. For an example, let's take an extract of the onet.xml file for a publishing (note for clarity this is an extract only - a full version is available at the link at the end of the article):

<Configuration ID="0" Name="BLANKINTERNET">

  <SiteFeatures>

    <Feature ID="A392DA98-270B-4e85-9769-04C0FDE267AA">

      <!-- PublishingPrerequisites -->

    </Feature>

    <Feature ID="7C637B23-06C4-472d-9A9A-7C175762C5C4">

      <!-- ViewFormPagesLockDown -->

    </Feature>

    <Feature ID="F6924D36-2FA8-4f0b-B16D-06B7250180FA">

      <!-- Office SharePoint Server Publishing -->

    </Feature>

  </SiteFeatures>

  <WebFeatures>

    <Feature ID="00BFEA71-4EA5-48D4-A4AD-305CF7030140" > </Feature>

    <Feature ID="22A9EF51-737B-4ff2-9346-694633FE4416">

      <!-- Publishing -->

      <Properties xmlns="http://schemas.microsoft.com/sharepoint/">

        <Property Key="ChromeMasterUrl" Value="~SiteCollection/_catalogs/masterpage/BlueBand.master"/>

        <Property Key="WelcomePageUrl" Value="$Resources:cmscore,List_Pages_UrlName;/default.aspx"/>

        <Property Key="PagesListUrl" Value=""/>

        <Property Key="AvailableWebTemplates" Value="*-ProjectX#0"/>

        <Property Key="AvailablePageLayouts" Value="ThreeColumnLayout.aspx"/>

        <Property Key="AlternateCssUrl" Value="" />

        <Property Key="SimplePublishing" Value="false" />

      </Properties>

    </Feature>

  </WebFeatures>

  <Modules>

    <Module Name="LoginPage" />

    <Module Name="Images" />

    <Module Name="Home" />

  </Modules>

</Configuration>


  • The Configuration element represents settings to be used with the selected definition, allowing groups of settings to be reused across definitions for flexibility
  • SiteFeatures /WebFeatures - specifies which Features should be automatically activated when the definition is used to create a site collection or child site respectively. This is key to our overall aim in this series of creating a site definition which applies custom unique permissions to sites created from it.
  • AvailableWebTemplates property of publishing feature - can be used to restrict which site definitions can be used to create child sites within sites created from this definition. This can be useful to prevent your content creators adding a team site onto your public-facing .com website for example. Here I'm specifying that only the 'ProjectX' definition with Configuration '0' can be used for child sites.
  • AvailablePageLayouts property of publishing feature - can be used to restrict which page layouts can be used within sites created from this definition. Again, this can be useful in controlling the look and feel of your website.
  • Modules - a module is a set of files to be automatically added when sites are created. Note it's also possible to specify which web parts should be added by default to a web part page by using the AllUsersWebPart element.


Deploying site definitions


What I really want to focus on however, is how site definitions can be packaged into a Solution to simplify deployment. This is typically most useful when deploying to multiple environments (e.g. test, staging, production) and/or deploying to a farm which consists of multiple SharePoint web servers. If you don't have this requirement, you may want to consider the simpler process of copying the XML files around manually, as detailed in the WSS SDK.

Before we start, let me highlight that Visual Studio Extensions for Windows SharePoint Services (VSeWSS) is a useful tool for creating and deploying custom site definitions, and I'd recommend looking into it for this requirement if you haven't already. However, I'm illustrating the 'manual' way here to hopefully provide an understanding of the nuts and bolts.

So, to package these files as a Solution manually, we follow the SDK instructions to get our customized onet.xml and webtemp*.xml files, but then place the files in a similar folder structure to the existing site definition files found under the 12 folder. I recommend creating a Visual Studio project as the best way to group these files (VSeWSS also follows this approach). This means you should end up with something looking like this:



Note we also have a .ddf file which is used with makecab.exe to build the Solution package - see my article on building and deploying Solution packages for details on the full process here. Effectively, we need to build the Solution by passing the .ddf file as a parameter to makecab.exe, and then run the STSADM -o addsolution and STSADM -o deploysolution commands to deploy to our target SharePoint site.

Once this is done, on the 'create site' screen we should see our new template appear:



Users can now use this definition to create sites which automatically have all the functionality and appearance we specified upfront. If we then need to deploy the definition to other environments, it's a simple case of copying the .wsp file there and running the STSADM commands. We are now well on our way to creating a site definition with custom permissions associated with it.

The set of files used in this article are at http://sharepointchris.googlepages.com/creatinganddeployingcustomsitedefinition

Updating existing site definitions


Finally, a quick note on updating definitions. Care needs to be taken here as often you will want to update files which are in use by sites already created with the definition - this can break things! Generally adding to a definition is OK, but modifying/deleting things can cause problems.

So a good technique is to copy the existing definition, add the updates and deploy for new sites to use, but also hide the earlier version so it cannot be used going forward. This is accomplished by removing the webtemp*.xml file from the TEMPLATE\\XML directory. Any sites already provisioned from the earlier version of the definition will continue to run fine, since you're leaving the actual definition (onet.xml etc.) intact over in TEMPLATE\SiteTemplates.

Remember also that new Features can be stapled to existing site definitions (affecting only new sites which are created, not existing ones), and this can be useful in avoiding having to update the site definition itself. See my article on Feature-stapling for more details.

So that's site definition basics. Next in the series - how to go beyond simple site definitions : add custom code which will execute when sites are created!

10 comments:

Randy said...

I am working on this right now. I am attempting to customize the permissions within my site definition. I know through the UI you can break inheritance from the parent, but I a searching for how to do this and create custom groups and permission for my site at creation time. I've already got a feature for handling the site creation event working and it auto-generates several lists, I just need to find the right API to use in creating the permissions.

Chris O'Brien said...

Hi Randy,

Yep, sounds like you're trying to solve the exact same problem I solved. Am afraid you'll have to wait for the other articles though!

Alternatively, if you want to communicate offline, leave me another comment with your e-mail address (I won't publish it to the blog - all comments are moderated), and I'll contact you directly with my solution. Saves you waiting a few days for the articles etc.

Cheers,

Chris.

Anonymous said...

Hi Chris,

I am working on the similar stuff. I want to modify the look-n-feel of the MOSS search pages for my site. Let me know what could be the best approach to do this.

Thanks,
John

Chris O'Brien said...

Hi John,

I've not worked in this area I'm afraid, though as far as I can see it's possible to drop the search web parts onto your own custom pages.

Maybe check that out to see if it's a valid approach.

Best of luck,

Chris.

Farrukh Ijaz said...

Hi Chris,

I was working on creating custom site definition for using "Publishing" site definition, but i got following error while creating site collection:

"The Office SharePoint Server Publishing Infrastructure feature must be activated at the site collection level before the Publishing feature can be activated."


Then I used the "webtempProjectX.xml" and "onet.xml" from your solution that also has publishing feature, but I got the same error.
Please help.

Thanks,
Farrukh

Chris O'Brien said...

Hi Farrukh,

Hmm, I'm not sure why you'd get this error. The key line which tells SharePoint to activate the site collection publishing feature is this one:

<Feature ID="F6924D36-2FA8-4f0b-B16D-06B7250180FA">

So long as you have this in your XML it should be automatically activated when a site collection is created from the definition. Remember though, that this feature probably needs to be activated on the site collection beforehard in order to create any webs from the definition.

HTH,

Chris.

SharepointNewbie said...

Is there any information on Elements.xml schema. I'm not sure which tags are needed or what each one is for. Could you clarify on the structure of Elements.xml? Thanks.

Chris O'Brien said...

Sure. This info is spread over several MSDN pages, but can be found at http://msdn.microsoft.com/en-us/library/ms414322.aspx.

HTH,

Chris.

Anonymous said...

I am aiming to make an application that creates automaticly a sharepoint site from an existing template by using XML files ( I think that onet.XML is the right one).
I made my template as an stp file but now i think i need to roll back my work with a site defintion.
Things are still fuzzy for me.
Am I in the right path ?
And can you help me find my way through with some tricks or advices ?

Chris O'Brien said...

@Anonymous,

Yes, that's exactly what a site definition provides in SharePoint - a template (with XML defining the site features/functionality/page layouts etc.). So you're looking in the right place - if my article doesn't explain site definitions in a good way for you, suggest checking out the MSDN documentation on site definitions.

HTH,

Chris.