There are two ways to share or reuse sites in SharePoint, templates or definitions. Site Defintions are complete site specifications that get installed as features usually and site templates are a single cab file with just the difference between the current and starting site definition that the site was based on. It is much easier to create a site template and deploy than site definitons. In order to create a site defnition you use the SharePoint solution generator to create a Visual Studio project and then from then on you make your changes to the files directly not the site when modifications are to be made.
The major benefit of Site Definitions is that you are able to make modifications to them and all sites created from them will be also modified, sort of. If of course some of the modifications were done in the SP designer then mods to the defintion may have no impact as pages may be unghosted. Also if you are in the business of developing these sites for market as a product then you are faced with additional restrictions, you cannot simply regenerate the solution to include your modifications as the generated solution is actually a feature based model of the site definition and the feature ID's will be different for all components including content types. So after you have delivered this site definition product to a customer you pretty much have to only make changes directly to the already generated solution files or figure our some model of merging in the changes ( I did this btw with a macro that merged the newly generated solution with the already deployed one and it still was a pain).
SO. What i chose as a deployment model for sites that are products is instead site templates. There are problems with this model of course to be worked around but it is easier than site definitions.
Some problems with using Site Templates as released product sites are as follows:
-
in order to include custom pages and images libraries you must check off the include content box when generating the site definition and this can mean junk makes it into your sites.
-
dataview web parts fail as they are still pointing at the original list ids and not the newly generated ones
-
if someone modifies the site defintion that your site template is based on then you could have a broken site.
-
updates to released sites are more complicated as existing sites must be recreated and the content restored.
How to go about using site templates as your deployment model:
-
You cannot simply have your customers add your template to their site collection because of the above listed problems. You must use a site collection feature to deploy your site template, so create an empty SharePoint project and add your required feature.xml files to allow for feature deployment.
-
add a new VS cab file project to your solution and add in all the files that are in your sites .stp file ( to do this rename the .stp file to .cab and open it in explorer view), then have the output of the cab file be a new .stp file that your feature in step one will use.
-
Edit the manifest.xml file in the #2 project to remove any data in document libraries or lists that you don't want your customers to receive.
-
create a feature event class in the #1 project to handle the site creation and cleanup of the resulting site. Here is a function I created to handle creating a site from the file:
public static SPWeb CreateWebFromTemplate(SPWeb baseWeb, String templatePath,String templateName,
String siteRelativePath, String siteTitle, String siteDescr,Boolean addToParentNav)
{
SPWeb tWeb = baseWeb.Webs[siteRelativePath];
SPWeb newWeb = null;
if (tWeb == null || !tWeb.Exists)
{
SPList wtcl = baseWeb.GetCatalog(SPListTemplateType.WebTemplateCatalog);
//1st remove existing template
try {
if (wtcl.RootFolder.Files[templateName] != null ) {
wtcl.RootFolder.Files[templateName].Delete();
}
}
catch (Exception ex2)
{
}
byte[] b = File.ReadAllBytes(templatePath);
SPFile spf = wtcl.RootFolder.Files.Add(templateName, b);
spf.Update();
SPWebTemplateCollection wtc = baseWeb.Site.GetCustomWebTemplates(1033);
if (templateName.Contains("."))
templateName = templateName.Substring(0, templateName.IndexOf("."));
SPWebTemplate spwtemplate = wtc[templateName];
newWeb = baseWeb.Webs.Add(siteRelativePath, siteTitle, siteDescr, 1033, spwtemplate, false, false);
newWeb.NoCrawl = true;
if (addToParentNav)
{
Boolean addIt = true;
for (int i = 0; i < baseWeb.Navigation.TopNavigationBar.Count; i++)
if (baseWeb.Navigation.TopNavigationBar[i].Url.ToLower() == siteRelativePath.ToLower()) addIt = false;
if (addIt)
{
SPNavigationNode spwMenuItem = new SPNavigationNode(siteTitle, siteRelativePath, true);
baseWeb.Navigation.TopNavigationBar.AddAsLast(spwMenuItem);
baseWeb.Update();
}
}
}
return newWeb;
}
5. The next step in the activation class is to clean up the site. I used some of the code that was generated by the solution generator and retro fitted it. It depends on a provisioner.xml file to handle the list id remapping but could be made more automatic by examining the manifest.xml file in the cab instead. Here is the class to do this SiteCleanup.cs
6. The above steps will be fine for first deployments for updating existing customers you will need to back up all the list and document library content and reapply it after the site is recreated. This step can be part of the feature deactivation and activation process also.
If there is continued interest in the concept of the post I will continue it with greater detail. So please comment.
Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks