When you setup a workflow in SharePoint UI, there are two screens. One with the general workflow settings and the second to adjust some specific settings like the approvers and the notification message. The first screen is not so hard to update in the object model, the second gives you more headache. You need to change the property AssociationData of the SPWorkflowAssociation which is contains an XML string with several properties, not so intuative.
To make my life a little easier, I have created a wrapper class to update these properties. Hope this helps you out!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.ComponentModel;
namespace myProject
{
public class WorkflowAssociationData
{
#region properties
public enum AccounTypeOption { User, SharePointGroup };
public enum AssignmentTypeOption
{
[Description("Allemaal tegelijk (parallel)")] parallel,
[Description("Eén tegelijk (serieel)")] serial
};
public enum DurationUnitsOption
{
[Description("Dag(en)")] day,
[Description("We(e)k(en)")] week,
[Description("Maand(en)")] month
};
private XDocument xmlData;
public XDocument XmlData
{
get { return xmlData; }
set { xmlData = value; }
}
public string NotificationMessage
{
get { return readNodeValue("NotificationMessage"); }
set { setNodeValue("NotificationMessage", value); }
}
public int DurationforSerialTasks
{
get { return int.Parse(readNodeValue("DurationforSerialTasks")); }
set { setNodeValue("DurationforSerialTasks", value.ToString()); }
}
public DurationUnitsOption DurationUnits
{
get { return ((DurationUnitsOption)Enum.Parse(typeof(DurationUnitsOption), readNodeValue("DurationUnits"))); }
set { setNodeValue("DurationUnits", value.GetDescription()); }
}
public bool CancelonRejection
{
get { return bool.Parse(readNodeValue("CancelonRejection")); }
set { setNodeValue("CancelonRejection", value.ToString().ToLower()); }
}
public bool CancelonChange
{
get { return bool.Parse(readNodeValue("CancelonChange")); }
set { setNodeValue("CancelonChange", value.ToString().ToLower()); }
}
public bool EnableContentApproval
{
get { return bool.Parse(readNodeValue("EnableContentApproval")); }
set { setNodeValue("EnableContentApproval", value.ToString().ToLower()); }
}
public AssignmentTypeOption AssignmentType
{
get { return ((AssignmentTypeOption)Enum.Parse(typeof(AssignmentTypeOption), readNodeValue("AssignmentType"))); }
set { setNodeValue("AssignmentType", value.GetDescription()); }
}
#endregion
private WorkflowAssociationData() { }
/// <summary>
/// Create a new object with the default or existing XML
/// </summary>
/// <param name="xml"></param>
public WorkflowAssociationData(string inputXml)
{
XmlData = XDocument.Parse(inputXml);
}
/// <summary>
/// Update the approvers for this workflow
/// </summary>
/// <param name="displayName"></param>
/// <param name="accountName"></param>
/// <param name="accountType"></param>
public void UpdateApprovers(string displayName, string accountName, AccounTypeOption accountType)
{
insertPersonElement("Assignee", displayName, accountName, accountType);
}
/// <summary>
/// Update the CC receivers for this workflow
/// </summary>
/// <param name="displayName"></param>
/// <param name="accountName"></param>
/// <param name="accountType"></param>
public void UpdateCc(string displayName, string accountName, AccounTypeOption accountType)
{
insertPersonElement("CC", displayName, accountName, accountType);
}
/// <summary>
/// Attach the person element to the node <nodeName>
/// </summary>
/// <param name="nodeName"></param>
/// <param name="displayName"></param>
/// <param name="accountName"></param>
/// <param name="accountType"></param>
private void insertPersonElement(string nodeName, string displayName, string accountName, AccounTypeOption accountType)
{
XNamespace d = ""http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields">http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields";
XNamespace pc = ""http://schemas.microsoft.com/office/infopath/2007/PartnerControls">http://schemas.microsoft.com/office/infopath/2007/PartnerControls";
XElement dElement = XmlData.Descendants(d + nodeName).First();
if (dElement.Descendants().Count() == 0)
{
XElement el = new XElement(pc + "Person",
new XElement(pc + "DisplayName", displayName),
new XElement(pc + "AccountId", accountName),
new XElement(pc + "AccountType", accountType.ToString())
);
dElement.Add(el);
}
}
private string readNodeValue(string name)
{
XNamespace d = ""http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields">http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields";
XElement el = XmlData.Descendants(d + name).First();
return el.Value;
}
private void setNodeValue(string name, string value)
{
XNamespace d = ""http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields">http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields";
XElement el = XmlData.Descendants(d + name).First();
el.Value = value;
}
}
public static class EnumMethods
{
/// <summary>
/// Get the description from the enum
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string GetDescription(this Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
}
}
}