Skip to main content

Cloud

A Site Definition that Creates a Copy of Another Site

I’ll describe a solution where we leveraged the SharePoint Content Migration API inside a Feature receiver to automatically generate exact copies of existing sites on demand.

We recently had a requirement to create multiple new site definitions, with the wrinkle thrown in that the users should be able to change a site definition on-demand without intervention from IT.The site definitions were to be used across dozens of site collections.

 

Ideally the users wanted to be able to configure a ‘template site’ somewhere in SharePoint, and have that site serve as the template for any site created with the given definition.The users could then update this template site, and any future sites based on that definition would essentially be copies of the template.

 

This presented a challenge, because it’s a bit different than how SharePoint normally works.Normally you decide what the site definition will include, and build your definition accordingly.The definition then lives in the 12 hive, and any changes require an update to the definition files.

 

Another option of course is to back the template site up as an STP template file, and make that available in the Site Template gallery.This is a good option to allow fairly easy site template updates (at least there’s no server file updates), but it just wouldn’t work well in this particular scenario:

  • In an STP, publishing pages tend to get customized (unghosted), we did not want this
  • An STP file has a low size limit
  • The end users would need to understand how to create a new STP, and then distribute the updated STP across the many site collections
    • If we would have gone with an STP-based solution, we would have built a utility to simplify this process.

 

SharePoint provides another way to create duplicates of existing sites, using the Backup & Restore functionality, creating a CMP file.CMP’s have advantages over STP’s in that there’s no customization of pages, a higher size limit, and most importantly we could automate the process to be totally seamless to the end users.

 

The basic solution consists of the following components:

  1. A site definition, defining a mostly blank site
    1. We can have multiple ‘configurations’ in a single site definition, useful for our multiple site
    2. Each configuration will display on the “Create New Site” page as a site template option
  1. A Feature
    1. Include this feature in each site definition configuration
    2. The Feature is empty, except that it calls a Feature receiver class
  1. A Feature receiver class – this is where the work is done
    1. This class will look for the template site, create a backup CMP of the template, and then restore that site on top of the newly created site.
    2. Leverages the Content Migration API in the SharePoint object model
  1. A site collection to house the template sites
    1. Along with some housekeeping bits

 

OK, so let’s review each component in a bit more detail….

The site definition’s ONET.xml file contains multipleconfiguration definitions, each looking essentially like the below.This example is for an “Accounting” site, and the custom Feature is in bold: (… is just some standard Features)

<Configuration ID=”0″ Name=”Accounting”>

<Lists />

<Modules>

<Module Name=”DefaultBlank” />

</Modules>

<SiteFeatures>

</SiteFeatures>

<WebFeatures>

<!– COPY SITE TEMPLATE FEATURE–>

<Feature ID=”A32F2EC8-D07A-4c6c-AC09-6FD91BA15555″>

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

<Property Key=”TemplateSiteName” Value=”Accounting”/>

</Properties>

</Feature>

</WebFeatures>

</Configuration>

Notice the “TemplateSiteName” property – the Feature receiver uses this value to determine which Template site to use as the source for the site being created.And don’t forget to create a new webtemp xml file to make these available!http://msdn.microsoft.com/en-us/library/ms447717.aspx

The Feature’s Feature.xml file is pretty simple.Notice we do set Hidden=”TRUE” to avoid having the Feature appear in the Feature gallery.

<?xml version=”1.0″ encoding=”utf-8″ ?>

<Feature Id=”A32F2EC8-D07A-4c6c-AC09-6FD91BA15555″

Title=”Source Site Copy”

Description=”This feature copies a source SPWeb into a new SPWeb.”

Version=”1.0.0.0″

Scope=”Web”

Hidden=”TRUE”

ReceiverAssembly=”PBCustomCode.FeatureReceivers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38e98″

ReceiverClass=”PBCustomCode.FeatureReceivers.SiteCopyReceiver”

xmlns=”http://schemas.microsoft.com/sharepoint/” >

</Feature>

 

The Feature receiver class is where the bulk of the work takes place.It’s custom code running in an assembly.For a good overview of how to create a Feature receiver, check here:http://www.nnihlen.com/blog/archive/2006/12/04/724.aspx

When a user chooses one of our custom site definition configurations, the class executes when the Feature is activated, which happens automatically during site creation.Here’s a breakdown of the

FeatureActivated method in our custom class:

  1. Find the Template site
    1. We have a custom SharePoint list at a known location in the Template site collection, with 2 colums:the Template Site Name and the URL of the template site.
    2. Doing a CAML query on this list, using the TemplateSiteName property value as a key, locate the URL of the template site.
      1. string sourceTemplateName = properties.Feature.Properties[“TemplateSiteName”].Value;
  1. Generate a CMP backup of the template site
    1. Find a good example of how to export to a CMP and then import it here: http://msdn.microsoft.com/en-us/library/aa981161.aspx
    2. You’ll want to save the CMP to a known location on the server.I name it with a GUID, and save it to a custom folder in the 12 hive.I also delete the file once I’m done with it.
  1. Import the CMP file right on top of the site we’re currently creating
    1. See the same example of how to export to a CMP and then import it here: http://msdn.microsoft.com/en-us/library/aa981161.aspx
    2. Import it directly into the URL of the new site.Add this line to the code, just after the line importSettings.SiteUrl = destinationSiteUrl; :

importSettings.WebUrl = web.ParentWeb.Url;

  1. A few important things to keep in mind:
    1. The SPWeb.Name value of the new site must be the same as the source site.It’s unlikely that your user happened to choose the same name as the template author, so we simply temporarily rename the new site with the same name.We’ll change it back later.
      1. To get a handle on the new site’s SPWeb object:

SPWeb newWeb = (SPWeb)properties.Feature.Parent;

  1. Both the Export and Import process should be run with SPSecurity.RunWithElevatedPriviliges
  2. Both the Template site and the destination site must have been created with the same site definition configuration
    1. So, keeping with our Accounting example, we need to create the Template site (in the Template Site Collection) by using the Accounting site template.
    2. When you create a Template site, you don’t want your Feature receiver class to execute.We avoid this by having the Feature receiver first check the URL of the current SPSite object.If it’s the same as the known Site Template Site Collection, we skip execution of any actual code.This allows the Template site to be created without any complications.
  1. Cleanup
    1. Delete the CMP file
    2. Rename the SPWeb.Name to the original value (as created by the end user)

 

OK, now you’re ready to try it out:

  1. In your site template site collection, create a new site using one of your custom site definitions
    1. Configure the site with lists, libraries, web parts, permissions, etc.
  1. Now, in a different site collection, create a new site using the same custom site definition
    1. The Feature receiver should activate.
    2. The code finds the URL of the template site, based on the TemplateSiteName property in the configuration definition.
    3. It will generate a CMP file at the location you specify.
    4. The code will temporarily rename your new site with the same name as the template site
    5. The CMP file will be imported right on top of your new site
    6. The code will rename your site to the original name, and delete the CMP file
  1. When the site creation process completes, you should have an exact duplicate of your template site.

 

I hope someone finds this approach useful, it has served us well so far.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.