In the first part of this serie on SharePoint Solution Generator I just went through the creation of a site definition project, compiling it, deploying it, and create a new site based on our new site definition. Now that we know that that part works, it is time to look into what we exactly are getting in the site definition project as created by the SharePoint Solution Generator. The SharePoint Solution Generator is part of Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions, a set of tools and templates for creating solutions for SharePoint 2005 that recently came out in beta. See this blog post for more information.
As a quick recall what we are looking at: I created a site based on the out of the box team site site definition, created a site definition solution from it with the SharePoint Solution Generator, which resulted in a compilable and deployable Visual Studio 2005 C# project with the following structure:
A good look at onet.xml
A site definition is described by its onet.xml file. A small recap from the Windows SharePoint Service SDK on the function of onet.xml:
Functions of ONET.XML
ONET.XML has the following functions:
Defines the top and side navigation areas that appear on the home page and in list views.
Specifies the list definitions that are used in the site definition and whether they are available for creating lists on the Create page.
Specifies document templates that are available for creating document library lists on the New Document Library page and specifies the files used in the document templates.
Defines the base list types from which default Microsoft Windows SharePoint Services lists are derived.
Specifies the configurations of lists and modules that are used within site definitions.
Site Definition Tasks with ONET.XML
The following kinds of tasks can be performed in ONET.XML to customize a site definition:
Modify navigation areas for the home page and list pages.
Add a list definition as an option to the Create page.
Add a document template for creating document libraries.
Define a configuration for a site definition, specifying the lists, modules, files, and Web Parts that are included when a site is instantiated.
Because we created our site definition solution from an untouched instance of the wss team site, it is an interesting excercise to compare the onet.xml file in our site definition solution with the onet.xml file in the wss team site site definition (sts).
A good way to do such a comparision is by using a good diff tool, I used the SuperDiff power toy for Visual Studio 2005:
During the comparison the following things came to my attention:
- Resources get expanded. The original site definition uses resource files for all texts in the site definition. Our new site definition has all the texts expanded into the language we selected when creating the instance of the site we created our site definition project from (see picture above). This is understandable, on creation of the site the resource references in the onet.xml are expanded into the selected language. But actually this is a pity and a bit of a design flaw in WSS. WSS would have been better designed if it was possible to have resource references in the site instance as well. In MOSS 2007 there is such a feature for the PublishingWeb sites called variations. But what does this mean: it is not possible to create an instance of an existing language agnostic site definition, make some changes, and publish it again in a language agnostic way. The only thing you can do to accomplish this is to create a tool that rewrites the expanded text strings back to their resource file references. Good opportunity for a third-party tool here? There is one exception where the expanded resource is turned into a resource reference again: the NavBarPage element with the link to the Home of the site, probably because that one is assumed to be always there.
- Only one configuration. The SharePoint built-in site definitions have a concept called Configurations: based on the same site definition and list definitions, different configurations can be specified where a configuration describes which lists, modules, site features and web features to include when creating an instance of that configuration of the site definition. For example the sts site definition has three configurations: Default (STS#0), Blank (STS#1) and DWS = Document WorkSpace (STS#2). On creating a site definition project based on an existing site, it only knows of one configuration, the configuration used for instantiating the site. This configuration is always called the Default configuration with ID 0.
- Web parts has all properties. A web part has a large set of properties, and most properties have a default value. An example of such a property is IsVisible with a default value true. In the built-in site definitions only the required properties are included, in the created site definition solution all properties are included, but hey, who cares! Another thing is that web part properties can use resource strings as well, but those are expanded in the site definition solution.
Are the above points a show stopper? No absolutely not! If you want to create a really language agnostic version of your site definition that utilize resource files for your different supported language you have to do some extra work. In most cases you will be creating a solution for a customer in a chosen language.
The Site Provisioning Handler
The Site Provisioning Handler is a feature that enables the execution of code on provisioning an instance of a site based on the site definition. The feature has web scope and is defined as follows:
<Feature Title="TeamSite" Id="fe034860-4954-4b13-859f-892267dc0045" Description="" Version="220.127.116.11" Scope="Web" Hidden="TRUE" DefaultResourceFile="core" ReceiverAssembly="TeamSite, Version=18.104.22.168, Culture=neutral, PublicKeyToken=3b0f9fb38a73e4fc" ReceiverClass="TeamSite.TeamSite" xmlns="http://schemas.microsoft.com/sharepoint/"> <ElementManifests> <ElementFile Location="provisioner.xml" /> </ElementManifests> </Feature>
The ReceiverAssembly is the assembly created by compiling the code in the site definition solution. The relevant code for the provisioning feature can be found in the partial files SiteProvisioning.cs and SiteProvisioning.internal.cs. Especially the internal file is interesting, it contains the code as defined by the developers of the SharePoint Solution Generator. The code in this file does the following on provisioning of a new site:
- Restore web properties for the site
- Add custom CSS files available in the site in a folder with the name _styles to the site using the SPWeb.CustomizeCSS method (what does this do? I assume writing out links to these CSS files in all pages rendered for the web.)
- Restore Data View Web Part guids outside web part zones
- Restore Data View Web Part guids inside web part zones
Creating a site definition containing data view web parts has always been a mess. Data View Web Parts use all kind of GUID's to reference to list instances in a site. But on site definition time you don't know these GUID's yet. Another problem are the GUID's for web part connections This code seems to fix these problems, but I need more time to dive into the exact innerworkings.
The feature uses a provisioner.xml file containing specifications of things to fix. Our site definition has the following provisioner.xml file:
<SiteSettings> <!-- _filecategory="Provisioner" _filetype="File" _filename="provisioner.xml" _uniqueid="b8b1d607-d3ea-4a77-9302-2dc5c6d57e0f" --> <ListInstances> <ListInstance Id="9d519060-66f4-4bd6-9216-be608493d134" Title="Announcements" FeatureId="00bfea71-d1ce-42de-9c63-a44004ce0104" /> <ListInstance Id="f7a6a984-f2bb-4ddb-a131-cd9ae58e645e" Title="Calendar" FeatureId="00bfea71-ec85-4903-972d-ebe475780106" /> <ListInstance Id="258accc5-3f74-460d-8ce8-2d682f5de4df" Title="Links" FeatureId="00bfea71-2062-426c-90bf-714c59600103" /> <ListInstance Id="69f5806c-ebcf-40ec-bce8-bcfa65eb8e58" Title="Master Page Gallery" FeatureId="00000000-0000-0000-0000-000000000000" /> <ListInstance Id="65a1e744-6ba6-433f-a1c1-a75d31a0f713" Title="Shared Documents" FeatureId="00bfea71-e717-4e80-aa17-d0c71b360101" /> <ListInstance Id="655db2ef-1ae9-4ea0-9e31-d8ed15402539" Title="Tasks" FeatureId="00bfea71-a83e-497e-9ba0-7a5c597d0107" /> <ListInstance Id="587c255b-ffde-4cd0-b042-fba67f20ba65" Title="Team Discussion" FeatureId="00bfea71-6a49-43fa-b535-d15c05500108" /> </ListInstances> <WebProperties> <WebProperty Key="vti_extenderversion" Value="22.214.171.12407" /> <WebProperty Key="vti_defaultlanguage" Value="en-us" /> <WebProperty Key="vti_categories" Value="Business Competition Expense\ Report Goals/Objectives Ideas In\ Process Miscellaneous Planning Schedule Travel VIP Waiting" /> <WebProperty Key="vti_approvallevels" Value="Approved Rejected Pending\ Review" /> </WebProperties> </SiteSettings>
The exact possibilities within this file will be the topic of a future blog post, if I ever get to it.
The resulting solution file: TeamSite.wsp
The final result of all the work is a SharePoint solution file with the extension .wsp. See this blog post by Chris Johnson for some more background info. This solution file can be deployed to your development server or your server farm.
A .wsp file is actually just a CAB file that is renamed. If you rename it to a file .cab extension you can have a peek into it:
<Click the image to enlarge it>
But this is actually the exact same structure as you can find in your build output directory:
Is this all?
There is a short answer and a long answer.
First the short answer: no. I only exported a site I made no modifications to, so it was still very close to it's underlying site definition. This was on purpose, to see how far it would match its underlying site definition. If you have a more complex site with modification the whole thing will become way more complex.
Now the long answer: no. Given your site definition project, you can extend it with additional features, your own site provisioning code, your own content types, new list definitions, additional web parts, custom field controls, additional modules etc. etc. The Visual Studio 2005 Extensions for SharePoint give you all the tools do do exactly this. More on this in a future blog post.