Custom site provisioning provider

Up until a week ago, I thought the only 2 ways to make a template for a site where Site definition and Site Template.

Both ways required that you figure out a lot of XML syntax, feature ids lists ids etc… for any code you want to run on the created site, you need to staple another feature and if you need to run code after the site is provisioned, you need to spawn another thread that will sleep until the site is provisioned. Possible but not very intuitive or easy.

Then when I needed to create a custom publishing site to be used as a template for sub sites, I found custom site provisioning provider while reading this post.

I will probably never code another site template any other way from now on.

The example shows how to do it with run as system but it is not necessary because templates are used to create sites by users with full control so they will have enough rights to run the code. The downloadable code is a good start though.

Using custom site provisioning provider is mainly implementing the SPWebProvisioningProvider interface.

All the tasks are performed in in the: public
override
void Provision(SPWebProvisioningProperties props)

The first thing to do is to apply a standard template to the new site so we have something to start with.

I find it best to start with “STS#1”, the blank template. This gives you an empty provisioned site to add whatever is needed by the requirements. Once a template is implemented with “props.Web.ApplyWebTemplate(SITE_TEMPLATE);” the site is provisioned, so you don’t need to spawn threads and such to work with the created site, it is ready to be modified.

Little XML after all

It will not be SharePoint solution without some xml for good measures right? So here is the minimum.

In a module named “ProvisioningData” add a file named as your project with the features that will be used in the site (Later I will show how to find out the GUIDs for the features)

In the {SharePointRoot}\Template\1033\XML folder , we need a file named webtemp_{your project name}.xml

It will include the name, title, description, image URL, Display category and a reference to the provisioning data.

The Display category and the image URL will allow distinguishing your template in the UI

Image, Category and description

Adding features

The example shows how to iterate the provisioning data for features but they can be added directly in the code too, using the ID.

For the site site.Features.Add(new
Guid({the ID of the feature}));

For the sub site web.Features.Add(new
Guid({the ID of the feature}));

Make sure you know the scope the feature is for and not to add a feature that exists in the scope alread. (Activated)

Adding Lists

What can be better than figuring IDs of list types? Intellisense off course. Adding lists is as simple as this:

You can add fields to your lists at the same time to further your customization without figuring out the XML syntax like building ONET.XML. Again Intellisense is much easier

Adding pages

Pages can be added as files to a module; text can be changed to customize the particular provisioning (for example, embed in the text, the site title or instructions for the administrator) then added to the root or a folder in the site.

See method “AddPage” in the attached example.

Adding web parts in pages

If we started with a blank site, the web parts are not incorporated in the pages yet.

So we have the opportunity to insert web parts in the zones we want in our pages. We must know the zone IDs of the page and the order in the zone we want the web parts to go in.

There are few types of web parts; the example uses 2 of them:

  1. WebPart for this type you need the existence of the template to be in the web part gallery of the site collection (activated)
  2. ListViewWebPart this will show an existing list or library with a view.

Controlling Navigation

We also have the opportunity to customize the top and quick launch links. The example shows the publishing navigation because the template has the publishing feature but the same can be done with none publishing only the classes will be from Microsoft.SharePoint.Navigation Namespace rather than publishing.

We can:

  1. Programmatically decide how pages and sub sites will be referenced.
    1. “Global” refers to the top navigation
    2. “Current” refers to the quick launch.
  2. Programmatically remove the headers (Libraries, Lists etc…)
  3. Programmatically reorder the links and add new custom ones.

 

Finding GUIDs of features

I found out from a utility that gives you the name by GUID of feature in CodePlex that you can enumerate the Feature Definitions of a farm like so:

SPFarm oFarm = SPFarm.Local;

foreach (var oFeatureDev in oFarm.FeatureDefinitions)

{

System.Diagnostics.Debug.WriteLine(string.Format(“Feature {0} Id= {1} scope {2} ”

, oFeatureDev.DisplayName, oFeatureDev.Id ,oFeatureDev.Scope));

 

So you can get a dictionary of name and ID of features that you can use.

You can also use PowerShell

 

 

The attached solution includes 2 types of provisioning projects, guess which of them I preferJ.

Advertisements

About Ofer Gal

SharePointer
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s