Wednesday, April 29, 2009

Publishing Site Provisioning

I recently ran into an issue with creating a site template that where I wanted to use the Publishing Feature. My end goal was to create a real site definition but I first wanted to try to create template directly in SharePoint. I quickly found out that if you have the "Office SharePoint Server Publishing" Feature turned, on the "Save site as template" will not be available. The most common solution that many suggested was to simply turn off the Publishing Feature, create the site template and then manually turn on the Pushing Feature.


However this would not work well because I am building an automated site provisioning processes using K2 blackpearl. Basically in this K2 blackpearl process I use an InfoPath form, get approval on the site request, and then dynamically generate the site with custom SharePoint groups. We are trying to drive SharePoint Governance with K2 blackpearl which will ensure that the site topology is organized well, SharePoint groups and users are managed in a repeatable process and system administrators can be less involved with creating sites. As well, I want to use customized site templates to ensure that all sites are presented in the same manner instead of being a hodge-podge mess of content. We are even going as far as adding standardized content types into the site templates with K2 workflows mapped to the content types to ensure that publication of the content always goes through a standard process.


Back to the original problem at hand – knowing that I am creating an automated process to site provisioning I cannot expect users to go in and manually turn on the Publishing Feature on the site. The options I came up with were the following:

  1. Create my own site template and in the ONET.xml add a dependency to turn on the Publishing Feature.
  2. Create stapling Feature that would turn on the Publishing Feature.
  3. Write some code that would turn on the Publishing Feature.
  4. There are more – but will stick to this for now…

Option 1 – Did not work as intended. I wanted to use the STS template. I followed best practices, created my own site template and then added <Feature FeatureId="94C94CA6-B32F-4da9-A9E3-1F3D343D7ECB" /> to the <WebFeatures> element in the onet.xml file. I also modified the <Modules> to have several custom web parts displayed on the default.aspx. Doing this made sure that the Publishing Feature was turned on when the site was provisioned by SharePoint. However the Publishing Feature would completely wipe out my home page (default.aspx) and all the changes I made to default.aspx in the onet.xml file were gone!!!


Now, if a manually create my site template and then manually turn on the Publishing Feature the default.aspx will not get wiped out. Since the Publishing Feature is being turned during the actual site creation process within SharePoint, SharePoint is allowing the Publishing Feature to take over the homepage. So this would not work for me.


Option 2 – My next solution was to create the following Site Stapling Feature:

<Feature Id="13F62CC1-22DE-4719-AA44-1BCACD9E2D50"
Title="ML Demo KB Site Staple"
Description="Associates publishing and content type binding to Site Template."
Version="1.0.0.0"
Scope="Site"
Hidden="FALSE"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="SiteStaple.xml" />
</ElementManifests>
</Feature>


<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<!-- Web Publishing -->
<FeatureSiteTemplateAssociation Id="94C94CA6-B32F-4da9-A9E3-1F3D343D7ECB" TemplateName="KB#0" />
<!-- KB Content Type Binding -->
<FeatureSiteTemplateAssociation Id="AD644A91-BA8B-45ff-89FD-F96BCBEDC3BD" TemplateName="KB#0" />
</Elements>

As you can see the FeatureSiteTemplateAssociation is used to turn the custom features I need, including the Publishing Feature. The result was the exact same as Option 1. Again because the Publishing Feature is being activated during SharePoint's site provisioning process the default.aspx page is being overridden.

Option 3 – My ultimate solution was to add some code into my K2 blackpearl process to activate the Feature. I was pretty happy to say to that point I had no code yet in my process – however that is just not possible some days but that is why K2 blackpearl is so great. I basically added the following lines of code into my site provisioning process and I was able to completely replicate what I was able to do manually as a user within SharePoint.


The K2 Process






Code from "Activate Site Features"

//Activate the Features...
using (SPSite site = new SPSite(K2.StringTable["SharePoint Site Collection URL"]))
{
string webURL = K2.StringTable["KB Collaboration Site Logical Path"] + "/KB" +
K2.ProcessInstance.DataFields["New KB Number"].Value;

using (SPWeb web = site.OpenWeb(webURL))
{
SPFeatureCollection features = web.Features;

features.Add(new Guid(K2.StringTable["Publishing Feature"]), true);
features.Add(new Guid(K2.StringTable["Web Publishing Feature"]), true);
features.Add(new Guid(K2.StringTable["KB Content Type Binding Feature"]), true);
}
}

No comments: