Working with Association Data in MOSS Workflows

I received a couple of comments in response to me previous post on Custom Association and Custom Initiation forms regarding how to use the Association and Initiation data collected, from within the workflow code. I had answered in my responses that you just access the AssociationData and InitiationData members of the WorkflowProperties, which return the data as XML strings. You then just work with that XML as required.

Here I will present some sample code for actually working with the XML coming from the custom AssociationData.

First, I would like to step back though and look at designing the Association Data. Typically when working with any InfoPath form, I start from the data side, and develop an XML Schema for the data (ideally, this is done as part of the overall design of the solution being developed, and includes all of the data design for the solution). The code snippet below shows the schema I developed for this example.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://t4g.com/TestSchema.xsd"
           elementFormDefault="qualified"
           xmlns="http://t4g.com/TestSchema.xsd"
           xmlns:mstns="http://t4g.com/TestSchema.xsd"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
   <xs:element name="AssociationInitiationData" type="AssociationInitiationDataType" />
   <xs:complexType name="AssociationInitiationDataType">
      <xs:sequence>
         <xs:element name="TaskDescription" type="xs:string" />
         <xs:element name="AssignTo" type="xs:string" />
      </xs:sequence>
   </xs:complexType>
</xs:schema>

Note that this schema represents both the Association Data structure, as well as the Initiation Data. It is necessary for these two to share a schema and namespace, though the Association form need not populate all of the fields.

A Custom Association Form can then be developed in InfoPath based upon this schema, and deployed as described in my previous post.

Now, how do we access this Association Data from within our workflow?

I implemented a simple serializable class matching the schema, as shown below.

[Serializable()]
public class AssociationData
{
   private String _TaskDescription;
   private String _AssignTo;

   public String TaskDescription
   {
      get
      {
         return this._TaskDescription;
      }
      set
      {
         this._TaskDescription = value;
      }
   }

   public String AssignTo
   {
      get
      {
         return this._AssignTo;
      }

      set
      {
         this._AssignTo = value;
      }
   }
}

I also implemented a helper class (creatively named) to support loading the Association Data into this class (note that this helper handles both the Initiation and Association data):

public class Helper
{
   public static InitiationData DeserializeInitiationData(string xmlString)
   {
      using (MemoryStream stream =
         new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
      {
         XmlSerializer serializer =
            new XmlSerializer(typeof(InitiationData), "http://t4g.com/TestSchema.xsd");
            InitiationData data = (InitiationData)serializer.Deserialize(stream);
            return data;
      }
   }

   public static AssociationData DeserializeAssociationData(string xmlString)
   {
      using (MemoryStream stream =
         new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
      {
         XmlSerializer serializer = new XmlSerializer(typeof(AssociationData), "http://t4g.com/TestSchema.xsd");
         AssociationData data = (AssociationData)serializer.Deserialize(stream);
         return data;
       }
   }
}

Given these two classes, it is then simple to access the Association Data from within the workflow. For example, add a private member to the workflow class:

private AssociationData _associationData;

Then from within the onWorkflowActivated activity, add the following code:

String AssociationDataXml = workflowProperties.AssociationData;
_associationData = Helper.DeserializeAssociationData(AssociationDataXml);

The association data can then be accessed from within our _associationData object as required. The Schema, and the AssociationData class definition, can be modified as required to add additional fields.

I was considering another post about doing the same thing for InitiationData, but it works exactly the same way. So unless someone really insists, I will not bother.

%d bloggers like this: