Tuesday, September 23, 2008

How to pass parameters to workflow programmatically

Hi All,

Workflow, being my passion for working and always many times i come across to a task related to workflow , i explore many things.

In this post, i would like to share my knowledge about How to pass parameters to workflow programmatically.

Why do you need to pass the paramter to the workflow?

Answer is simple, there might be a chance where you do not use the Assoication and Initiation form with the workflow, everything is dependent on runtime. In this fashion there is no use of using the Association and Initiation form.

So sometimes you need to use the parameters for the workflow which you can pass it at the time of triggering the workflow from code.

I usually enjoy doing work with workflow programmtically. Because everything is possible with code that is what i bilieve.

So Here let me take you to a small trip to a way you can pass the workflow programmatically.

Please go through my post Starting Workflow Programmatically regarding starting workflow from code to know about WorkflowManager and WorkflowAssociation classes, which i will not cover in this post. here we will actually concentrate on passing the parameter.

To Pass the Paramter, First all you need to do is make one class and place Serializable attribute on it and define public properties and one public method which serializes the data in to the XML Format so that it becomes generic for using in any application to even pass it to Web Services.



So, lets start.

(1) Define one class with properties

[Serializable()]
public class WorkflowParameters
{
private string _ZipCode = default(string);


public string ZipCode
{
get { return _ZipCode; }
set { _ZipCode = value; }
}


private string _CountryCode = default(string);

public string CountryCode
{
get { return _CountryCode; }
set { _CountryCode = value; }
}

public string getInitXmlString(WorkflowParameters objParams)
{

WorkflowParameters data = new WorkflowParameters();

data._CountryCode = objParams._CountryCode;

data._ZipCode = objParams._ZipCode;


using (MemoryStream stream = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(WorkflowParameters));

serializer.Serialize(stream, data);

stream.Position = 0;

byte[] bytes = new byte[stream.Length];

stream.Read(bytes, 0, bytes.Length);

return Encoding.UTF8.GetString(bytes);

}
}

}

Here as you can see we have defined two properties ZipCode and CountryCode as an example. you make paramters accordingly to your need.

(2) Next, step is to dynamically execute the workflow, for this code you can refer post 1. I am working with event handler of a list, so here is a code which demonstrate the idea about executing workflow from event handler. change this code according to the code where you writing it.

SPWorkflowManager objWorkflowManager = null;
SPWorkflowAssociationCollection objWorkflowAssociationCollection = null;

SPListItem item = properties.ListItem;

objWorkflowManager = item.Web.Site.WorkflowManager;

objWorkflowAssociationCollection = item.ParentList.WorkflowAssociations;

foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection)
{
//Find the GUID for the workflow association

WorkflowParameters objParams = new WorkflowParameters();

objParams.ZipCode = "12345";
objParams.CountryCode = "USA";

string strSerializedParams = objParams.getInitXmlString(objParams);

objWorkflowAssociation.AssociationData = strSerializedParams;

if (String.Compare(objWorkflowAssociation.BaseId.ToString("B"),
"{workflow_ID}", true) == 0)
{
objWorkflowManager.StartWorkflow(item, objWorkflowAssociation,
objWorkflowAssociation.AssociationData, true);

}
}

As you can see here we have created an object of our previous defined class which is serializable. we set the properties and passed it to a public method of the same class and then we get the string as in the form of XML, which is then assigned to the AssociationData of workflowassociation which is passed to a workflow.

(3) Now you need to retrive these data in the workflow. Now you have to go to a Workflow Code. Let us assume that we fetch these data in Workflow Invoke Activity.

//Assume that this is the activity that executes when workflow triggers

private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{

//Fetch with workflow properties InitiationData property which gets the
//Parameters passed to it.

string strParametrsPassed = workflowProperties.InitiationData;

//Now this string returns you string in XML format which looks like this,

//<?xml version="1.0"?>
//<WorkflowParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-//instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
// <ZipCode>12345</ZipCode>
// <CountryCode>USA</CountryCode>
//</WorkflowParameters>

}


Ignore any whitespaces in the output shown for XML. it is just to get the idea.

And, so you got XML here, just play with XML class and use these parameters in your code.

We can always refine any of the above code, this is just to demonstrate the concept.

That's it. your job is done.

3 comments:

Anonymous said...

Hi,
AWESOME!!

shouldnt the following line:
string strParametrsPassed = workflowProperties.InitiationData

be:
string strParametrsPassed = workflowProperties.AssociatedData
????

Anonymous said...

Great, many thanks.

Here is a shorter version of the Parameters class using auto-properties:

[Serializable]
public class WorkflowParameters
{
public string AuthorisingUser { get; set; }
public string AuthorisingGroup { get; set; }
public string PolicyRef { get; set; }

public string GetInitXmlString()
{
using (MemoryStream stream = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(WorkflowParameters));
serializer.Serialize(stream, this);
stream.Position = 0;
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
return Encoding.UTF8.GetString(bytes);
}
}
}

SharePoint Kings said...

Thanks, it might be user full. (but we didn't tested :) )




Share your SharePoint Experiences with us...
As good as the SharePointKings is, we want to make it even better. One of our most valuable sources of input for our Blog Posts comes from ever enthusiastic Visitors/Readers. We welcome every Visitor/Reader to contribute their experiences with SharePoint. It may be in the form of a code stub, snippet, any tips and trick or any crazy thing you have tried with SharePoint.
Send your Articles to sharepointkings@gmail.com with your Profile Summary. We will Post them. The idea is to act as a bridge between you Readers!!!

If anyone would like to have their advertisement posted on this blog, please send us the requirement details to sharepointkings@gmail.com