Subscribe
E-mail
Download View Codeplex Project Site
Powered by: newtelligence dasBlog 1.9.7174.0
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2008, Rich Finn
dasBlog MOSS template
In our current SharePoint project, we have a custom site definition based on the out-of-box Publishing Site with Workflow. We found a little problem with this though, because when the out-of-box Features for Publishing and it's Parallel Approval workflow are activated, the default SharePoint Approvers group is the only group that is set to approve a publishing page that has been sent into the workflow. The problem is, we want to inherit the parent site's workflow settings - otherwise known as the association data - because our application has 'channels' of content that each has a different group who can approve the content in their appropriate channel.
The group that can approve publishing pages in each channel is defined in the root web of the channel by doing nothing more than editing the Parallel Approval workflow on the Pages list, and then setting the correct group on the People Picker for the workflow approvers property. Since channel owners can create new sites in their channel using our custom provisioning process, we don't want them to have to go into the Pages list workflow settings to set the correct group every time, because as we all know, people make mistakes. Why not automate this process and set the right approvers group for the channel owner when the new site is created?
To do this, we created a Feature that we included in our custom site definition. When a new site is created and the Feature is activated, we execute the following code:
using System; using System.Collections.Generic; using System.Text; using Microsoft.SharePoint; using System.Diagnostics; using Microsoft.SharePoint.Workflow; using System.Xml; using Microsoft.SharePoint.Publishing; namespace Demo { public class FeatureReceiver : SPFeatureReceiver { public override void FeatureActivated(SPFeatureReceiverProperties properties) { //get the SPWeb object for the Feature's scope SPWeb currentWeb = properties.Feature.Parent as SPWeb; //set the AllowUnsafeUpdates property to true so we can apply the change to the workflow currentWeb.AllowUnsafeUpdates = true; //get the parent web of the current web - this is where the correct workflow settings are SPWeb parentWeb = currentWeb.ParentWeb; //get the Pages list from the current web using the PublishingWeb object SPList currentWebPublishingList = PublishingWeb.GetPublishingWeb(currentWeb).PagesList; //get the current web Pages list's workflows SPWorkflowAssociationCollection currentWebWorkflows = currentWebPublishingList.WorkflowAssociations; //if the site has workflows, we need to get the parent web's workflow and apply the same approvers to it if (currentWebWorkflows.Count >= 1) { //find the parallel approval workflow SPWorkflowAssociation currentWorkflowAssociation = currentWebWorkflows.GetAssociationByName("Parallel Approval", currentWeb.Locale); //empty container for the parent pages list workflow SPWorkflowAssociation parentWorkflowAssociation = null; //get the parent site's pages list SPList parentPagesList = PublishingWeb.GetPublishingWeb(parentWeb).PagesList; //if there's workflows attached, we need to find the Parallel Approval workflow if (parentPagesList.WorkflowAssociations.Count > 0) { parentWorkflowAssociation = parentPagesList.WorkflowAssociations.GetAssociationByName("Parallel Approval", parentWeb.Locale); } //if we have the parent workflow, we need to copy the review settings to the child if (parentWorkflowAssociation != null) { //xmldoc for the parent association data XmlDocument parentAssociationData = new XmlDocument(); parentAssociationData.LoadXml(parentWorkflowAssociation.AssociationData); //xmldoc for the child workflow association data XmlDocument currentAssociationData = new XmlDocument(); currentAssociationData.LoadXml(currentWorkflowAssociation.AssociationData); //we need to create a namespace manager object because the xml data we want is //namespaced with 'xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD"' //the following code was obtained from John Wood's blog //url: http://www.dotnetjunkies.com/WebLog/johnwood/archive/2005/08/25/132153.aspx //this code will add all namespaces in the xml to the namespace manager, allowing us to correctly //create XPath queries to retrive the data we need XmlNamespaceManager nsmgr = new XmlNamespaceManager(parentAssociationData.NameTable); foreach (XmlAttribute attr in parentAssociationData.SelectSingleNode("/*").Attributes) { if (attr.Prefix == "xmlns") nsmgr.AddNamespace(attr.LocalName, attr.Value); } //get the Reviewers node from the parent workflow XmlNode parentReviewers = parentAssociationData.SelectSingleNode("//my:Reviewers", nsmgr); //get the Reviewers node from the child workflow XmlNode currentReviewers = currentAssociationData.SelectSingleNode("//my:Reviewers", nsmgr); //set the Reviewer node of the child workflow to be the same as the parent currentReviewers.InnerXml = parentReviewers.InnerXml; //update the child workflow's association data currentWorkflowAssociation.AssociationData = currentAssociationData.OuterXml; //update the child workflow association in the database currentWebPublishingList.UpdateWorkflowAssociation(currentWorkflowAssociation); } } //make sure you dispose of the parentWeb object parentWeb.Dispose(); } public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { } public override void FeatureInstalled(SPFeatureReceiverProperties properties) { } public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { } } }