Archive

Author Archive

Multi-level Workflows in Microsoft SharePoint

December 1st, 2009 Sandeep Komalan 1 comment

Workflows are a powerful and yet surprisingly easy to use feature in SharePoint. You can use workflows to manage a business process or any series of tasks required to get a job done. You might use a workflow, for example, to manage expense reporting, manage time sheet or leave applications.

Out of the box SharePoint approval workflow allows you to configure the workflow on a list or on any library. It is pretty straight forward to configure with static approvers and can specify when to start and end the workflow.

But, if you want your workflow to choose an approver based on some criteria then things can get a little complex. I have provided an business example of  of how you can make this happen along with relevant code.  Ignify recently implemented a multi-level routing workflow for a  non-profit organization serving 24 million members. I have built on our experience from that project and other Microsoft SharePoint Server implementations 

Scenario: You have a leave request application in your SharePoint and the company policy is leave request should go to the submitting employee’s supervisor for approval.

In the above scenario, the supervisor can be different for each employee. How will you pass this dynamic supervisor information to your approval workflow?

Solution:

  • Determine the GUId or Index value of your approval workflow.
  • Determine the Association data that the workflow requires to start.
  • Modify the Association data to provide appropriate approvers.

Steps :

  1. Configure the approval workflow to the list or a library with some specific values.
  2. Don’t specify the option of starting the workflow when an item is created or modified.
  3. After configuring the other necessary parameters, your list or library is set with an approval workflow.

Now your list or library will have the workflow configured and the workflow will have the association data which we can modify and start the workflow.

Accessing the workflow from code.

One of the biggest developer-focused enhancements in SharePoint is, for handling server-side events. For example, when a user performs an action that modifies content in a SharePoint site—say, creating or modifying an item from a list—there is an opportunity for a developer to respond to this user action with an event handler that executes server-side logic written in C# or Visual Basic.

So here we will make use of the list events to modify the workflow association data and start the workflow.

Creating a list event:

  1.  Open visual studio
  2.  Create a new project with project type as class library.
  3.  Add reference tot he class library Windoes Sharepoint Services(Microsoft.Sharepoint.dll)

Sample code

Override the Item added event in this scenario because we are going to start the workflow when a leave request is being made.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Microsoft.SharePoint;

using Microsoft.SharePoint.Workflow;

using System.IO;

using System.Diagnostics;

namespace DynamicApproval

{

public class LeaveApproval : SPItemEventReceiver

{

public override void ItemAdded(SPItemEventProperties properties)

{

try

{

SPSite objSiteCollection = new SPSite("Your Sharepoint Site URL");

SPWeb objSPSite = objSiteCollection.OpenWeb();

SPList objList = objSPSite.Lists[properties.ListId];

 

//Disabing the event firing during the process.

this.DisableEventFiring();

objSPSite.AllowUnsafeUpdates = true;

 

SPListItem objLeaveItem = properties.ListItem;

string LeaveRequestor = Convert.ToString(objLeaveItem["Employee name filed in the List"]);

//Getting the approver from the list where the employee information is maintained.

//If you have a well structured Active directory you can query the AD

//and get the respective superviosr of the employee.

string Approver = GetApprover(LeaveRequestor);

//Setting the due date

DateTime dt = System.DateTime.Now;

DateTime dtnew = dt.AddDays(7);

string strDueDate = dtnew.ToShortDateString();

SPWorkflowAssociation objAssociationTemplate = objList.WorkflowAssociations["Workflow Index or the Association GUID"];

//Sample association data.

//Asssociation data should be a well structured XML.

//Supplying the approver to the association data.

//In the same way you can add any number of approvers with a new <my:Person> tag thus making it as a multi level.

string AssociationData = "<my:myFields xml:lang=\"en-us\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:my=\"http://schemas.microsoft.com/office/infopath/2003/myXSD\">\r\n <my:Reviewers>\r\n \r\n <my:Person>\r\n <my:DisplayName>";

AssociationData = AssociationData + Approver + "</my:DisplayName>\r\n <my:AccountId>" + Approver + "</my:AccountId>\r\n <my:AccountType>User</my:AccountType>\r\n </my:Person></my:Reviewers>";

AssociationData = AssociationData + "\r\n <my:CC></my:CC>\r\n <my:DueDate xsi:nil=\"false\"></my:DueDate>\r\n <my:Description></my:Description>\r\n <my:Title></my:Title>\r\n <my:DefaultTaskType>1</my:DefaultTaskType>\r\n <my:CreateTasksInSerial>true</my:CreateTasksInSerial>\r\n <my:AllowDelegation>true</my:AllowDelegation>\r\n <my:AllowChangeRequests>true</my:AllowChangeRequests>\r\n <my:StopOnAnyReject>true</my:StopOnAnyReject>\r\n <my:WantedTasks xsi:nil=\"true\"></my:WantedTasks>\r\n <my:SetMetadataOnSuccess>false</my:SetMetadataOnSuccess>\r\n <my:MetadataSuccessField></my:MetadataSuccessField>\r\n <my:MetadataSuccessValue></my:MetadataSuccessValue>\r\n <my:ApproveWhenComplete>true</my:ApproveWhenComplete>\r\n <my:TimePerTaskVal>" + strDueDate + "</my:TimePerTaskVal>\r\n <my:TimePerTaskType xsi:nil=\"true\"></my:TimePerTaskType>\r\n <my:Voting>false</my:Voting>\r\n <my:MetadataTriggerField></my:MetadataTriggerField>\r\n <my:MetadataTriggerValue></my:MetadataTriggerValue>\r\n <my:InitLock>false</my:InitLock>\r\n <my:MetadataStop>false</my:MetadataStop>\r\n <my:ItemChangeStop>false</my:ItemChangeStop>\r\n <my:GroupTasks>true</my:GroupTasks>\r\n</my:myFields>";

//Starting the workflow.

objSiteCollection.WorkflowManager.StartWorkflow(objLeaveItem, objAssociationTemplate, AssociationData, true);

}

catch (Exception ex)

{

EventLog.WriteEntry("Starting Workflow", ex.Message, EventLogEntryType.Error);

}

}

/// <summary>

/// Getting the supervisor name of the employee from a sharepoint list.

/// </summary>

/// <param name="Employee">Name of the employee who submits the leave.</param>

/// <returns>login name of the approver.</returns>

private string GetApprover(string Employee)

{

string approver = string.Empty;

SPSite objSiteCollection = new SPSite("Sharepoint Site");

SPWeb objSPSite = objSiteCollection.OpenWeb();

SPList objApproverList = objSPSite.Lists["Employee information List Name"];

SPListItemCollection Collection = objApproverList.Items;

foreach (SPListItem item in Collection)

{

string EmployeeinList = Convert.ToString(item["Employee Name Field in the List"]);

if (EmployeeinList.ToLower().Trim() == Employee.ToLower().Trim())

{

string Approver = Convert.ToString(item["Approver field Name"]);

//Since the shapoint list item gives the person or name field name with id;Name format

//and hence we need to find out the login name of the approver for submitting to the workflow.

//The Id is being retrieved from the name returned using the substring.

int approverID = Convert.ToInt32(Approver.Substring(0, approverID.IndexOf(';')));

//Will return the user information based on the ID.

SPUser user = objSPSite.SiteUsers.GetByID(approverID);

if (user != null)

{

approver = Convert.ToString(user.LoginName);

}

break;

}

}

return approver;

}

}

}

Register the item added event to your list or library where the workflow is configured.

Now when an employee submits a new leave request, it will select the appropriate supervisor and starts the workflow.

Hope this will help in configuring the out of the box SharePoint approval workflow with dynamic approvers and also to configure any levels with the out of the box approval workflow capabilites rather than creating a new one from scratch.

This post is written by Sandeep Komalan. Sandeep is a Senior Technical Analyst – Web Application in the Microsoft SharePoint Practice at Ignify. Ignify has over 300 person years of SharePoint experience and internally leverages SharePoint as a tool to collaborate across all its offices and for all its projects. For help on SharePoint Services email us at sharepoint@ignify.com