Introduction

Microsoft SharePoint Server 2007 and Windows SharePoint Services 3.0 are excellent tools to help companies organize their content and make it available to those who need it within the business. As companies change and reorganize, this information must be adaptable also. For instance, one division within a company may have started using a meeting site to help organize and collaborate on a project; however, the project may have been taken over by another division with its own site. How can all of the existing information be saved and moved? Although MOSS 2007 and WSS are great platforms, the tools available do fall short in this area. This article will explain options and a possible solution to allow webs to be copied or moved from one location to another.

Background

Let's start by defining a scenario for use in this article. Your company has created a SharePoint site structure similar to this

Root

Austin

Dallas

Ft. Worth

El Paso

Divsion1

Divsion3

Divsion5

Divsion7

Divsion2

Divsion4

Divsion6

Divsion8

This is, of course, very simplistic since in a real-world application, each site would potentially have many lists and subsites; however, this will give us a starting point for discussion. Now, consider when Divsion8 moves from El Paso to Austin. Of course, the site could remain at its present location in the overall site structure, yet, one would logically think to look for it under Austin, not El Paso, since it now resides there. A new subsite could be created under Austin and all of the content manually moved; however, this is a tedious and labor intensive process, and will not preserve audit information or version history.

Warning This project uses SharePoint 2010 Beta and Visual Studio 2010. Although it should work in previous versions, it has not been tested.

Options for copying or moving a site

When needing to copy or move SharePoint sites or webs, the options are really limited.

Central Administrator Backup and Restore

The SharePoint Central Administrator site offers the Backup and Restore function. However, as we can see, it is not very granular. You can back up the entire web application, not a single site or web.

Stsadm

The venerable commandline tool stsadm.exe offers a more granular option for backup.

There is a limitation on size; backups using stsadm are limited to 15 GB or less, and if using SharePoint prior to SP2, you must also use setsitelock to prevent additions or updates to the site and its content while the backup is in progress. Also, alerts and workflows will not be preserved. To restore the site, you use the mirror command, restore. This is a time consuming two-step process, and can only be performed by someone with administrative rights and access to the stsadm application. Not for the average user.

SharePoint Designer

Using SharePoint Designer 2007, the site that is currently opened can be backed up using the Backup Web Site menu item under the Site -> Administration -> Backup menu.

To restore the backup to another location, you must first create the site, then restore it. A cumbersome three step process. Further limitations are that you must have access to SharePoint Designer, which not everyone will have.

SPExport/SPImport

Found in the Microsoft.SharePoint.Deployment namespace, these classes provide a method to basically backup and restore a site, web, list, and other objects in SharePoint, and are what the SharePoint Designer uses. To use SPExport or SPImport, you need to configure the process by using the respective settings classes.

This code will create an archive file named export.cmp that contains information about the site collection located at http://server/MySite and place it in the folder C:\SPBackup. Setting FileCompression = false will produce a compressed folder structure. OverwriteExistingDataFile = true tells SPExport to overwrite any existing files. Setting it to false will produce an exception if the export.cmp file already exists. The reverse operation would be as follows:

A minor point of interest is when setting CommandLineVerbose = true in the Settings objects, it will write output to a console window so you can see the extensive operations that are occurring during an export or import. Although there is an event ProgressUpdated in both the SPExport and SPImport classes, it does not send this information. Instead, it only sends information about the total number of objects and how many have been processed.

These are just some basic settings. Now let's take a more detailed look at the process and how it can be used to copy or move a web.

Copy/Move Web

Using the SharePoint API, we can create classes that expose a simple interface for copying or moving a web.

The first parameter is the URL of the web to be copied. The second parameter is the URL of the destination. In this case, we will end up with http://server/Austin/Division8 that is a copy of what is at http://server/Elpaso/Division8.

Validate Source Web

The first thing that must be done is to verify the existence of the source web.

An interesting note here is if we tried to call OpenWeb without passing the relative path of the web we are trying to open. As below, it would return the root web, http://myserver/Home in this case, and of course, SPWeb.Exists would return true.

SourceWeb = SourceSite.OpenWeb();

A cumbersome alternative would be to search the SPWebCollection and attempt to match the name. Using the StringComparer.CurrentCultureIgnoreCase would be necessary since the names and the URL may not be the same case.

Validate destination web

The destination web must be validated also. If a web already exists with the same name, we must check its type. It if is not the same as the source, an exception will be generated during the import process, so it must be deleted. It isn't necessary to create a new web as one will be created during the import process. If the webs are the same type, the destination will be overwritten with the source during the import process.

Finding the SPWebTemplate

When comparing the SPWebTemplate for webs, the obvious first place to look is the WebTemplate property. However, this does not give enough information for an accurate comparison. For instance, SPWeb.WebTemplate will return MPS for a web that was created with a Basic Meeting site template and STS for a Blank Site, but the actual template names are MPS#1 and STS#1, respectively. Where does this extra provisioning configuration information come from? Unfortunately, there does not appear to be any information in the SPWeb object that indicates the provisioning configuration; the only place this is available is in the WSS_Content database.

Here, we get the database connection string from the SPSite objects and look up the proper value in the Webs table. Of course, it should go without saying that accessing the database directly is not recommended, but, since this information is not available in the API, there is no choice.

Exporting the web

As stated above, the export process is configured using the settings class, SPExportSettings in this case.

What happens with the above code, however, is the entire site collection will be exported. Basically, a backup of the entire SharePoint site that is the root of the specified SiteURL. However, we are only interested in a single web. To export a single web, it needs to be added to the ExportedObjects collection. SPExport uses this collection to identify what needs to be exported. If this collection is empty, everything will be exported.

Hi Mark,
This is really an useful article. Granular backup restoration is not that too easy in MOSS 2007. However, SharePoint 2010 resolves this headache. I am trying to develop and utility using which admin can perform granual backup and restoration. SPImport and SPExport classes will be really useful. Thanks for sharing. Five Star from my side.