How to: Create a SP2007 Site Collection Template in VS2008 in XML only

So, the other day, I got a curious request. I was to provide a new site collection template, a custom template, that would be using no code whatsoever. The client did not want to deploy custom code to their production server. I had never created a site collection template before. Let alone one that would not be supported/built by/with code.

However, as most of the times is the case, the whole project was less impossible that it seemed at first. It was actually doable.

The following is rundown of the steps I took to create everything. It might not be entirely blog-material -as I was mostly keeping notes while creating the template- but it will be hugely helpful to anyone who runs into such a predicament.

How to create a site collection template that will provision list instances, list templates and web parts on the default.aspx page.

1. Start VS > New Project > SharePoint Templates > Blank Site Definition
2. As soon as the IDE loads, right click on the project and select PACKAGE (renames everything so that you will not have to manually do it).
3. From VS > View (menu) > Other Windows > WSP View (ctrl+W)
4. Press refresh (upper left hand corner in the solution explorer).
5. Edit the ONET.XML file
i. Replace the <SiteFeatures> section with :
<SiteFeatures>
<!– Standard MOSS Publishing Features –>
<Feature ID=”A392DA98-270B-4e85-9769-04C0FDE267AA” />
<Feature ID=”AEBC918D-B20F-4a11-A1DB-9ED84D79C87E” />
<Feature ID=”89E0306D-453B-4ec5-8D68-42067CDBF98E” />
</SiteFeatures>
ii. Replace <WebFeatures> section with :
<WebFeatures>
<!– Support for custom lists –>
<Feature ID=”00BFEA71-DE22-43B2-A848-C05709900100″ ></Feature>

<!– Support for Document Libraries –>
<Feature ID=”00BFEA71-E717-4E80-AA17-D0C71B360101″ ></Feature>

<!– Support for Picture libraries –>
<Feature ID=”00BFEA71-52D4-45B3-B544-B1C71B620109″ ></Feature>

<!– Support for Task lists –>
<Feature ID=”00BFEA71-A83E-497E-9BA0-7A5C597D0107″ ></Feature>

<!– Support for Workflow History lists –>
<Feature ID=”00BFEA71-4EA5-48D4-A4AD-305CF7030140″ ></Feature>

<!– Collaboration Lists –>
<Feature ID=”00BFEA71-4EA5-48D4-A4AD-7EA5C011ABE5″></Feature>

<!– Publishing Feature –>
<Feature ID=”22A9EF51-737B-4ff2-9346-694633FE4416″>
<Properties xmlns=”http://schemas.microsoft.com/sharepoint/”>
<Property Key=”ChromeMasterUrl” Value=””/>
<Property Key=”WelcomePageUrl” Value=”default.aspx”/>
<Property Key=”PagesListUrl” Value=””/>
<Property Key=”AvailableWebTemplates” Value=””/>
<Property Key=”AvailablePageLayouts” Value=””/>
<Property Key=”SimplePublishing” Value=”true” />
</Properties>
</Feature>

<!– Portal Navigation Properties Feature –>
<Feature ID=”541F5F57-C847-4e16-B59A-B31E90E6F9EA”>
<Properties xmlns=”http://schemas.microsoft.com/sharepoint/”>
<Property Key=”InheritGlobalNavigation” Value=”true”/>
<Property Key=”ShowSiblings” Value=”true”/>
<Property Key=”IncludeSubSites” Value=”true”/>
</Properties>
</Feature>
</WebFeatures>
6. Edit the webtempPROJECTNAME.SiteTemplate.xml file. Change stuff to match your project names. The Display Category is the name of the tab where the template will appear in when you create new site collections from the Central Administration.
<?xml version=”1.0″ encoding=”utf-8″?>
<Templates>
<Template Name=”MOSS.Publishing.SiteTemplate” ID=”10001″>
<Configuration ID=”1″
Title=”MOSS Publishing Site Template”
Description=”A publishing site template with the minimum required features for publishing sites.”
Hidden=”FALSE”
ImageUrl=”/_layouts/images/stsprev.png”
DisplayCategory=”Custom Development” />
</Template>
</Templates>
7. Right click the project and PACKAGE. Right click the project and DEPLOY (for local test environments). IISReset.
8. Visit the Central Admin and notice how the new site collection template appears in a new tab in the site collection creation GUI.

In order to provision the new site with lists, libraries, etc, you can either do so

1. through code in the OnActivated event in the SiteProvisioning. You would be leveraging the Object Model then. (for example, if you wanted to create a new list as soon as the site collection is created, you could do the following:

const string DEFAULTASPX = “/default.aspx”;
const string LISTVIEWTITLE = “Site Links”;
const string LINKLISTNAME = “Links”;
const string LINKLISTDESCRIPTION = “A custom list used to store links to sites”;
public string strLinkListID;

public void OnActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb currentWeb = properties.Feature.Parent as SPWeb)
{
//create the Links List
currentWeb.Lists.Add(LINKLISTNAME, LINKLISTDESCRIPTION, SPListTemplateType.Links);
strLinkListID = currentWeb.Lists[LINKLISTNAME].ID.ToString();
}
}
–> if you also wanted to add a content editor web part on the default.aspx page, you could also do that like:
//get the default.aspx page as an SPFILE
SPFile spfDefaultASPX = currentWeb.GetFile(DEFAULTASPX);

if (spfDefaultASPX.InDocumentLibrary)
{
if (!(spfDefaultASPX.CheckedOutBy == SPContext.Current.Site.RootWeb.CurrentUser))
{
spfDefaultASPX.CheckOut();
}
}
try
{
SPLimitedWebPartManager splWebPartManager = currentWeb.GetLimitedWebPartManager(currentWeb.Url+DEFAULTASPX, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
ListViewWebPart wpListView = new ListViewWebPart();
SPList spList = currentWeb.Lists[strLinkListID];
if (spList == null)
throw new ArgumentException(“List Not Found”);
wpListView.ListName = strLinkListID.ToUpperInvariant();
wpListView.TitleUrl = spList.DefaultViewUrl;
wpListView.WebId = spList.ParentWeb.ID;

wpListView.Title = LISTVIEWTITLE;

splWebPartManager.AddWebPart(wpListView, “Left”, 2);
}
finally
{
if (spfDefaultASPX.InDocumentLibrary)
{
spfDefaultASPX.CheckIn(“Page has been edited during activation”);
spfDefaultASPX.Publish(“Programmatically Publish”);
spfDefaultASPX.Approve(“Programmatically Published”);
}
}
[you would add the above, right under the previous bit of code that added the list]
)

2. The other way is to provision the lists and libraries through the XML files that are being deployed with the package you’re creating. The file you want to play with is the “onet.xml”

A. Locate the <Configurations> tag and create the new list as such:

<Configurations>
<Configuration ID=”1″ Name=”Blank”>
<Lists>
<List
FeatureId=”00BFEA71-2062-426C-90BF-714C59600103″
Type=”103″
Title=”Site Links”
Url=”$Resources:core,lists_Folder;/SiteLinks”
/>
</Lists>
<Modules>
<Module Name=”DefaultBlank”/>
</Modules>

</Configuration>
</Configurations>
Notice that the FeatureId for built-in lists is predefined (you can’t use whatever you come up with. In this example, we use a Link List. The link list’s type is 103. The featureId is 00BFEA71-2062-426C-90BF-714C59600103 -notice that it ends with 103)
Short list:
List Type                                        / Type                                    / FeatureId
Document Library                     / 101                                      / 00BFEA71-E717-4E80-AA17-D0C71B360101
Discussions                                   / 108                                     / 00BFEA71-6A49-43FA-B535-D15C05500108
Announcements                         / 104                                     / 00BFEA71-D1CE-42de-9C63-A44004CE0104
Links List                                       / 103                                     / 00BFEA71-2062-426C-90BF-714C59600103
Calendar List                                / 106                                    / 00BFEA71-EC85-4903-972D-EBE475780106
Tasks List                                       / 107                                    / 00BFEA71-A83E-497E-9BA0-7A5C597D0107
Picture Library                           / 109                                    / 00BFEA71-52D4-45B3-B544-B1C71B620109

(notice that although the above is the same for all types of lists, the Announcements list is different in that it needs to be listed in the XML file as:

<List FeatureId=”00BFEA71-D1CE-42de-9C63-A44004CE0104″ Type=”104″ Title=”$Resources:core,announceList;” Url=”$Resources:core,lists_Folder;/$Resources:core,announce_Folder;”>
<Data>
<Rows>
<Row>
<Field Name=”Title”>$Resources:onetid11;</Field>
<Field Name=”Body”>$Resources:onetid12;</Field>
<Field Name=”Expires”><ows:TodayISO/></Field>
</Row>
</Rows>
</Data>
</List>)

B. Once you have created your list, you can create a list view web part for your list on your default.aspx page. The reason you might want to choose the XML approach over the Object Model approach is that in this case, it is much easier to reference your list on your default.aspx page. Whereas in your programmatic approach you would have to reference the GUID (which will always be different, hence, you will run into problems) in the XML approach, all you need to do is the following:
In your onet.xml file, locate the area where it defines the DefaultBlank area.
<Modules>
<Module Name=”DefaultBlank” Url=”” Path=””>
(make sure you get the correct location in the onet.xml as the DefaultBlank will also appear much earlier in the file, inside the Configurations tag. You need to alter the DefaultBlank that is OUTSIDE of the Configurations tag.
You will notice that there’s already code that leverages the default.aspx page (<File Url=”default.aspx” NavBarHome=”True” Type=”Ghostable”>)
At the end of the AllUsersWebPart, add your list view as follows:

]]></AllUsersWebPart>
<View List=”Lists/SiteLinks” BaseViewID=”0″ WebPartOrder=”2″ WebPartZoneID=”Left” />
Notice that you will need to make sure you replace the name of your list in the Lists/SiteLinks, the BaseViewID references a view of the list, the WebPartOrder defines the horizontal placement of your list view (if there are other web parts on the page, and the WebPartZoneID defines where on the page you need the listview to appear (most common values = Left, Right)

If you want to also add a content editor web part, just add the following:
<!–START OF: CONTENT EDITOR WEB PART | WELCOME TEXT–>
<AllUsersWebPart WebPartZoneID=”Left” WebPartOrder=”1″>
<![CDATA[
<WebPart xmlns=”http://schemas.microsoft.com/WebPart/v2″ xmlns:cewp=”http://schemas.microsoft.com/WebPart/v2/ContentEditor”>
<Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
<TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>
<FrameType>Default</FrameType>
<Title>Welcome</Title>
<cewp:Content>The links below will take you to a specific site. Please note that you will only see links for which you currently have access.</cewp:Content>
</WebPart>
]]>
</AllUsersWebPart>
<!–END OF: CONTENT EDITOR WEB PART | WELCOME TEXT–>

——————————————————————————————————————————————————————————————-

If you want to provide a custom list, you should right click on your project name and select Add > New Item and then SharePoint > List Definition. You will then get a new folder in your Solution Explorer, named after the List name that you will provide, a number of .xml files (an instance.xml file too if you select to create an instance of the definition) and a number of .aspx pages for your display/edit/ create forms and the AllItems list view.

The list definition goes into the ListDefinition.xml file. You provide information such as the Name of the list and other generic properties. The SecurityBits property is interesting in that the first digit in the string controls who can view the items of the list and the second digit in the string controls who can edit the items.  The acceptable values are as follow:

For read access, the following are valid digits:
1 Users can read all items.
2 Users can read only their own items.

For edit access, the following are valid digits:
1 Users can edit all items.
2 Users can edit only their own items.
4 Users cannot edit items.

Inside the schema.xml file you can define specifics for the lists that will be based on your template. Say for example that you want to create columns in your list. You would create fields inside the <Fields> area. If you wanted to provide the ability to use some other Content Type inside your list, you would add a reference inside the <ContentTypes> area.

——————————————————————————————————————————————————————————————-
If you want to use your own master page, you need to do the following:
1. get a copy of the default.master page that you want to use (or, any other named .master page).
2. right click your project, in the folder “Site Definition”, add your master page. For example, customDefault.aspx.
3. open the default.aspx file and locate the Page directive line (<%@ Page language=”C#” MasterPageFile=”~masterurl/custom.master” Inherits=”Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c” %> <%@ Register Tagprefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls” Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %> <%@ Register Tagprefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities” Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %> <%@ Import Namespace=”Microsoft.SharePoint” %> <%@ Register Tagprefix=”WebPartPages” Namespace=”Microsoft.SharePoint.WebPartPages” Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>)
4. In that line, change the MasterPageFile=”~masterurl/default.master” to MasterPageFile=”~masterurl/custom.master”. NO MATTER WHAT YOU HAVE CALLED YOUR MASTER PAGE, YOU NEED TO USE CUSTOM.MASTER IN THE PAGE DIRECTIVE. SharePoint will do a string replacement of this string with the value contained in the CustomMasterUrl property of the site.
5. Open the onet.xml file and locate the Configuration node. Inside the configuration note add a CustomMasterUrl attribute and set it to “_catalogs/masterpage/customName.master”. For example: <Configuration ID=”1″ Name=”Blank” CustomMasterUrl=”_catalogs/masterpage/customDefault.master”> NOTICE THAT YOU WILL NEED TO PROVIDE THE CORRECT NAME FOR YOUR MASTERPAGE FILE HERE. IT WILL BE THE SAME AS THE MASTERPAGE FILE NAME IN YOUR SITE DEFINITION DIRECTORY.
6. In the <Modules></Modules> section WITHIN the <CONFIGURATION> add a single <Module Name=”CustomMasterPage” />
7. Outside of (at the end of) the CONFIGURATION node, there is another listing of <Modules>. In there, add the following: <Module Name=”CustomMasterPage” List=”116″ Url=”_catalogs/masterpage” RootWebOnly=”FALSE”><File Url=”customName.master” Type=”GhostableInLibrary” IgnoreIfAlreadyExists=”TRUE” /> </Module>
8. Save/Package/Deploy/IISReset and create a new site collection based on your site definition. It should deploy and use your new .master page file.
——————————————————————————————————————————————————————————————-
To create a picture library and populate with images.
0. Add your photo files and associated _t thumbnails in your Site Definition folder in your solution. Such as: 1. brandbar.gif and 2. brandbar_gif.jpg (you can use the same -thumbnail files- for your web versions).
1. create a list inside the <Configuration ID=”1″ Name=”Blank” CustomMasterUrl=”_catalogs/masterpage/customDefault.master”><Lists> like so:

<List FeatureId=”00BFEA71-52D4-45B3-B544-B1C71B620109″
Type=”109″
Title=”SystemPhotos”
Url=”images1″
/> (this will create a picture library named SystemPhotos UNDER a Lists folder)

2. STILL INSIDE THE CONFIGURATION add 3 modules:

<Module Name=”ImagePopulation” /> (the full photo displayed when you click on the web version)
<Module Name=”ImagePopulation_t” /> (for thumbnails)
<Module Name=”ImagePopulation_w” /> (for web versions – the ones SP2007 displayes when you click on the thumbnail)

3. OUTSIDE THE CONFIGURATION add the actual modules. The ones that you just used above, need to be defined. Here’s how:

<Module Name=”ImagePopulation” List =”109″ Url=”images1″ Path=””>
<!–These are the actual files–>
<File Url=”brandbar.gif” Type=”GhostableInLibrary” />
<File Url=”brandbar_bottom.gif” Type=”GhostableInLibrary” />
</Module>
<Module Name=”ImagePopulation_t” List =”109″ Url=”images1/_t” Path=”\_t”>
<!–These are the actual files–>
<File Url=”brandbar_gif.jpg” Type=”GhostableInLibrary” />
<File Url=”brandbar_bottom_gif.jpg” Type=”GhostableInLibrary” />
<File Url=”brandbar_middle_gif.jpg” Type=”GhostableInLibrary” />
</Module>
<Module Name=”ImagePopulation_w” List =”109″ Url=”images1/_w” Path=”\_w”>
<!–These are the actual files–>
<File Url=”brandbar_gif.jpg” Type=”GhostableInLibrary” />
<File Url=”brandbar_bottom_gif.jpg” Type=”GhostableInLibrary” />
<File Url=”brandbar_middle_gif.jpg” Type=”GhostableInLibrary” />
</Module>

MGR: the Intelogist

About MGR: the Intelogist

SharePoint Server developer, turned Sitefinity developer, turned Angular developer, turned SharePoint Online consultant, turned Unily consultant, turned O365 consultant... Never a dull moment!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

This site uses Akismet to reduce spam. Learn how your comment data is processed.