by Andreas

Sharepoint 2010 – programmatically set workflow initiation parameters

If you trigger workflows from the code behind of a custom webpart you might want to set some of the workflow initiation parameters to runtime values. I’ve seen some pretty ugly attempts to do this by alternating the SPWorkflowAssociation.AssociationData object using string.Replace for instance.. To save others the time and effort figuring out this I thought I’d share a method I wrote where this is done in a more proper and reliable way.

For simplicity the namespace is hardcoded, but you should be able to figure that part out for yourself. This is the default namespace, and will work unless you’ve tampered with it.

It pretty much just accepts the original association data (XML based) and the name of the initiation parameter plus the new value (this is only for string based variables, but you could easily add support for other types as well).

private static string AddVariableToWorkflowAssociationData(string originalAssociationData, string variableName, string variableValue)
{
    XNamespace dfs = "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution";
    XNamespace d = "http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields";

    var associationDataXml = XElement.Parse(originalAssociationData);

    if (associationDataXml == null ||
        associationDataXml.Element(dfs + "dataFields") == null ||
        associationDataXml.Element(dfs + "dataFields").Element(d + "SharePointListItem_RW") == null ||
        associationDataXml.Element(dfs + "dataFields").Element(d + "SharePointListItem_RW").Element(d + variableName) == null)
    {
        _log.Warn("AddVariableToWorkflowAssociationData() unable to find node '" + variableName + "' in association data");
        return originalAssociationData;
    }

    _log.Info("Setting workflow parameter '" + variableName + "' to '" + variableValue + "'");
    var nodeToChange = associationDataXml.Element(dfs + "dataFields").Element(d + "SharePointListItem_RW").Element(d + variableName);
    nodeToChange.SetValue(variableValue);

    return associationDataXml.ToString();
}

Invoke this method by getting a reference to the workflow you want to trigger (SPWorkflowAssociation), call my method with the original association data, and use the return value when starting the workflow:

string enhancedAssociationData = AddVariableToWorkflowAssociationData(wrkFl.AssociationData, "MyVeryOwnAssociationParameter", "SomeCrazyValue!!");
enhancedAssociationData = AddVariableToWorkflowAssociationData(enhancedAssociationData, "AnotherAssociationParameter", "AndYetAnotherCrazyValue");
siteColl.WorkflowManager.StartWorkflow(record, wrkFl, enhancedAssociationData, true);

Some of this code was altered on the fly for this blog post so compilation is not guaranteed. However, if you’re this deep into it to start with you should be capable of resolving that anyway!

  • Reddy

    All guys have already learned how to start the workflow pragmatically. By using the below post, we will learn how to run the ninetex workflow pragmatically even with “system account” also.
    http://sharepoint2010learnersworld.blogspot.com/2011/10/how-to-start-ninetex-workflow.html

    Note: Ninetex workflow can’t run with “system account” credential through coding.

  • Manuel

    Thank you for this, worked like a charm.

  • pontnou

    Thank you, simple, esasy and it works!

  • Erin

    I had no idea how the original AssociationData was constructed and my previous attempts to update it were completely wrong. This was simple and worked perfectly, thanks!

  • Anton

    Lots of thanks! Works greate!