Workflow Initiation and Association Forms in SharePoint 2010: GetInitiationData, Seralize<T>() and Deserialize<T>()

SharePoint 2010 in Visual Studio 2010 has made creating Windows Workflow Foundation (WF) workflows an awful lot easier. There are still one or two areas that can be confusing to new developers

One such region of confusion surrounds the Initiation Form – the form displayed whenever a user launches your workflow, that you can use to prompt for more information required to run your workflow. Similar uncertainty surrounds the Association Form – one that is displayed whenever a list administrator attaches your workflow to their list.

Thanks to the tooling in Visual Studio, it’s now easy to add either of these forms. Right-clicking your Workflow item in Solution Explorer and choosing “Add-> New Item” will give you:

Adding a New SharePoint Item in Visual Studio 2010

Selecting either Initiation Form or Association Form will add the appropriate artefacts to your code and also configures the Element manifest of the Workflow accordingly:

Element Manifest Changes to view Initiation Forms

Let’s say we wanted to ask the user a series of extra questions when they launch our workflow, such as their manager’s First Name, Last Name and Email Address, such that we can have access to that data within our running workflow later on.

We can now edit our new Initiation Form as an aspx page in Visual Studio. Let’s add some text boxes to capture the extra information:

image

The next question is often “how do we get this information to the workflow?” Inside the workflow itself is a SPWorkflowActivationProperties object which exposes two strings: InitiationData and AssociationData, which is respectively the data captured from the user during launch and association phases of the workflow.

The code behind for the Initiation Form has a string method called GetInitiationData(). Whatever string you return here is then available from inside your workflow using workflowProperties.InitiationData. It’s the same principle with Association Forms, GetAssociationData and AssociationData properties.

Clearly, we could go low-rent here and return a semi-colon delimited string or something naff of that ilk.

Alternatively you could store your properties temporarily in a class and then serialise that class to a string and return that. Then later in your workflow you could deserialise that back to an instance of your object.

You could put a lot of effort into this to get it really efficient, but the general principle is why not create a utility class to hold Serialise and Deserialise methods?

I’ve implemented the following candidate code using Generics to show how powerful the technique is:

public static string Serialise<T>(T item)
{
    XmlSerializer ser = new XmlSerializer(item.GetType());
    TextWriter sw = new StringWriter();
    ser.Serialize(sw, item);
    return sw.ToString();
}

public static T Deserialise<T>(string xml) where T : new()
{
    T returnObject = new T();
    XmlSerializer ser = new XmlSerializer(returnObject.GetType());
    XmlTextReader xtr = new XmlTextReader(new StringReader(xml));
    return (T)ser.Deserialize(xtr);
}

So, given a class, for example, to hold contact information:

public class Contact
{
    public string FirstName;
    public string LastName;
    public string Email;
}

You could put the following in your code behind for the Initiation Form:

// This method is called when the user clicks the button to start the workflow.
private string GetInitiationData()
{
    contact.FirstName = firstName.Text;
    contact.LastName = lastName.Text;
    contact.Email = email.Text;
    return Serialise<Contact>(contact);
}

Then in the code beside for your workflow you can get at the data again like this:

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    Contact contact = Deserialise<Contact>(workflowProperties.InitiationData);
    historyDescription = string.Format("Received Contact information: {0} {1} {2}",
        contact.FirstName, contact.LastName, contact.Email);
}

Hopefully this code will save you some searching and typing.

Comments

  1. Kamesh says

    Do we need to install any other VS components to get the Workflow Initiation Form and Association form?

    • Joel Jeffery says

      Hi Kamesh!

      Thanks for reading my blog!

      Workflow Initiation Form and Workflow Association Form are two project item templates you get with Visual Studio 2010 out-of-the-box. You create them by right-clicking the Workflow project item node you created in Solution Explorer, and picking Add Item. You don’t see them if you try and add them directly to the project. It has to be added to the Workflow item itself.

      Best of luck!

      joel

  2. Lee says

    Great post… I was trying to convince myself to delimit the returned string but thought I would have a look around first before going down the quick and dirty path – seeing this made me laugh “Clearly, we could go low-rent here and return a semi-colon delimited string or something naff of that ilk.”

    Just one question – what would be your preferred way of populating the association form with current values when an existing association is being modified?

  3. Shegit says

    Thank you very much, it saved me some time of researching.
    I had to laugh at same point as Lee.
    I’m just thinink about performance.
    If I have to convert it into string, than I have my procedure for that. And back again maybe.
    But the transfer volume is much shorter. What would you suggest?

    thanks, Shegit

  4. Robert says

    Lee, use the method PopulateFormFields in association form code behind to set current values:

    private void PopulateFormFields(SPWorkflowAssociation existingAssociation)
    {
    // Optionally, add code here to pre-populate your form fields.
    if (existingAssociation != null)
    this.txtBox.Text = existingAssociation.AssociationData;
    }

  5. J Herschel says

    Thanks a lot Joel, exactly what I was looking for and looks a LOT easier than WF in SharePoint 2007.

  6. Roberto A says

    I have created a workflow with an ASP.NET and it works, but only launching by hand the WorkFlow; if i associate the WorkFlow to the add and insert operations fof the List the WF goes on error: it is normal ?

    • Joel Jeffery says

      Hello Roberto!

      In your workflow where you parse workflowProperties.InitiationData, you probably want to check first that it is not empty or null. An auto started workflow will not have any data in the InitiationData string.

      Hope this helps!

      joel

  7. Peter Olsen says

    The Deserialize method could be shortened a bit, like this:

    public static T Deserialise(string xml)
    {
    XmlSerializer ser = new XmlSerializer(typeof(T));
    XmlTextReader xtr = new XmlTextReader(new StringReader(xml));
    return (T)ser.Deserialize(xtr);
    }

Trackbacks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>