NAnt task for SharePoint: Save SPWeb as site template to the filesystem
I love NAnt as a tool to automate deployment processes. Kris Syverstad created a nice set of NAnt tasks for SharePoint that he uploaded to a GotDotNet workspace. My latest task was to save a site as a site template to the filesystem for deployment to another system. I decided to create a task in the same spirit to Kris his tasks. You can add it to the set of tasks that Kris already created. That is what I did.
The code:
//
// NAnt.SharePoint Microsoft Sharepoint Server utility tasks.
// Copyright (C) 2006 Macaw, Serge van den Oever
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
using System;
using System.IO;
using System.Globalization;
using Microsoft.SharePoint;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Types;
namespace NAnt.SharePoint.Tasks
{
/// <summary>
/// Save SPWeb as template.
/// </summary>
/// <remarks>
/// <para>
/// Save a template of the SPWebs pecified by a Url on the local machine.
/// </para>
/// <note>
/// If the <see cref="Url" /> specified does not exist, a
/// <see cref="BuildException" /> will be raised.
/// </note>
/// </remarks>
/// <example>
/// <para>Delete a SPSite.</para>
/// <code>
/// <![CDATA[
/// <deletespsite Url="http://myserver/sites/mysite" />
/// ]]>
/// </code>
/// </example>
/// <example>
/// <para>
/// Save SPWeb as template. If the SPWeb does not exist, the task does nothing.
/// </para>
/// <code>
/// <![CDATA[
/// <savespwebastemplate url="${url}" templatename="myTemplate" title="My Template" description="A Template Of My Site" savedata="true" tofile="c:\template.stp" failonerror="false" />
/// ]]>
/// </code>
/// </example>
[TaskName("savespwebastemplate")]
public class SaveSPWebAsTemplateTask : Task
{
private string _url = "";
private string _templatename = "";
private string _title = "";
private string _description = "";
private bool _savedata = false;
private string _tofile = null;
/// <summary>
/// The URL for the SPWeb to save as template.
/// </summary>
[TaskAttribute("url", Required = true)]
public string Url
{
get { return _url; }
set { _url = value; }
}
/// <summary>
/// The name for the template.
/// </summary>
[TaskAttribute("templatename", Required = true)]
public string TemplateName
{
get { return _templatename; }
set { _templatename = value; }
}
/// <summary>
/// The title for the template.
/// </summary>
[TaskAttribute("title", Required = false)]
public string Title
{
get { return _title; }
set { _title = value; }
}
/// <summary>
/// The description for the template.
/// </summary>
[TaskAttribute("description", Required = false)]
public string Description
{
get { return _description; }
set { _description = value; }
}
/// <summary>
/// Boolean specifying if data of the SPWeb should be included in the template.
/// Only data up to 10Mb can be included.
/// </summary>
[TaskAttribute("savedata", Required = false)]
public bool SaveData
{
get { return _savedata; }
set { _savedata = value; }
}
/// <summary>
/// The file to save the template to.
/// </summary>
[TaskAttribute("tofile", Required = false)]
public string ToFile
{
get { return _tofile; }
set { _tofile = value; }
}
/// <summary>
/// Because ExecuteTask is protected added this function to debug the task.
/// </summary>
public void DebugTask()
{
ExecuteTask();
}
/// <summary>
/// Task for saving a SPWeb as template.
/// </summary>
protected override void ExecuteTask()
{
string templateFilename = TemplateName + ".stp";
try
{
using (SPSite site = new SPSite(Url))
{
try
{
using (SPWeb web = site.OpenWeb(site.ServerRelativeUrl))
{
// Delete site template with name TemplateName if it exists
SPDocumentLibrary webTemplates;
try
{
webTemplates = site.GetCatalog(SPListTemplateType.WebTemplateCatalog) as SPDocumentLibrary;
}
catch (Exception ex)
{
throw new BuildException(
string.Format("The site collection of the SPWeb '{0}' does not contain a Site Template Gallery.",
Url), Location, ex);
}
SPFolder folder = web.Folders["_catalogs"];
SPFolder subfolder = folder.SubFolders["wt"];
subfolder.Files.Delete(templateFilename);
}
}
catch (Exception)
{
// ignore, no template to delete
}
// Save the SPWeb as template
using (SPWeb web = site.OpenWeb())
{
// If no title is specified, use same as template name
if (Title.Length == 0)
{
Title = TemplateName;
}
web.SaveAsTemplate(templateFilename, Title, Description, SaveData);
}
}
Log(Level.Info, LogPrefix + "Save SPWeb '{0}' as template with name '{1}'.", Url, TemplateName);
}
catch (Exception ex)
{
// The SPS API will throw an exception when you try and create an
// instance of SPSite for a URL that doesn't exist.
throw new BuildException(
string.Format("Cannot save SPWeb '{0}' as template. Either the SPWeb does not exist, or savedata is true and the size of the SPWeb > 10MB, or there is already a template by this name.",
Url), Location, ex);
}
if (ToFile != null)
{
try
{
using (SPSite site = new SPSite(Url))
{
string templateUrl = site.Url + "/_catalogs/wt/" + templateFilename;
System.Net.WebClient objWebClient = new System.Net.WebClient();
objWebClient.Credentials = System.Net.CredentialCache.DefaultCredentials;
objWebClient.DownloadFile(templateUrl, ToFile);
}
}
catch(Exception ex)
{
throw new BuildException(
string.Format("The SPWeb '{0}' is saved as template '{1}' in the Site Template Gallery, but downloading the template to file '{2}' failed.",
Url, Name, ToFile), Location, ex);
}
}
}
}
}