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);

                }

            }

        }

    }

}

17 Comments

  • Plz tell me what other than NAnt Compiler must be present on the system for compiling Deployment Projects using NAnt Scripts

  • Hi Richa, you need visual studio!! Or the .Net SDK and compile manually.

  • It appears that NAnt.SharePoint.Tasks is no longer available anywhere that Google or Live Search can access.
    Is there a copy somewhere still?

  • Hello Serge,
    I am using the first part of your code in an ASP page where I have a button that is going to delete one template from the Template Gallery. Everything goes fine, instantiate the folder and subfolder and when I do the subfolder.Files.Delete(templateFileName) instruction I get the following exception:
    "The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again"
    Do you have any idea why I am getting this exception? any lights on this or where to look at it would be greatly appreciated.
    Regards
    David at Philly

  • Nice post. I study something tougher on totally different domains everyday.
    It is going to always be stimulating to find out content out of
    different writers and observe a minor bit something out of their store.
    Id choose to make use of some with the content on my blog
    whether you dont mind. Natually Ill offer you with a link in
    your web blog. Thanks for sharing.

  • Saved as a favorite, I like your web site!

  • I am not actually wonderful with English then again I find out hold this very easygoing to read
    .

  • I?¦ve recently started a blog, the information you give on this website has helped me vastly.
    Thanks for all of your time & work.

  • Be that the precise blog whenever you have wants to find
    out about this topic. You comprehend considerably it
    is nearly onerous to argue to you (not that I personally would
    needHaHa). You undoubtedly put an additional spin for a topic thats
    been discussing for some time. Nice stuff, only nice!

  • I’m new to your blog and i actually appreciate that the nice posts and great layout.
    `.`-,

  • I’m not sure where you have been getting your information, then again
    good topic. I needs to spend some time learning much more or understanding more.
    Thanks for great info I was seeking for this info for my mission.

  • not everyone would need a nose job in spite of
    this my girlfriend actually needs some rhinoplasty coz her nose is sort of crooked;

  • I enjoy you because of your own labor on this site. My daughter really likes going through
    internet research and it’s effortless to understand why.
    I determine all of the dynamic mode you offer efficient info on
    that the blog and therefore boost participation
    out of other ones on that the subject while our daughter is undoubtedly looking up
    plenty of things. Have fun with the rest of the new year.

    You are carrying out a pretty cool job.

  • Deference to author , some superb info .

  • laminate floorings give away a less costly and easier way to setup a
    fine flooring~

  • I am glad for writing to make you recognize of that the fabulous encounter our girl went through going through
    your blog. She discovered a wide variety of things, which included
    how it can be for instance to have a great giving mood to have
    other individuals easily have an understanding of the quantity
    of specialized matters. You truly did more than people’s desires.
    Thanks for delivering those informative, trusted, informative not
    to mention easy thoughts on that topic to Jane.

  • Great website right here! Additionally your web site starts up
    very fast! What host have been you getting service out of?
    Can you pass along your associate link for your host? I want
    my web site loaded up as fast because yours lol

Comments have been disabled for this content.