LinkedIn

Wednesday, 16 April 2008

My Sharepoint Workflow is not seeing my custom content type column

Just like to say a big thanks to Andrew Carter for pointing me in the right direction on this one.

Andrew Carter's post
http://suguk.org/forums/thread/9820.aspx
Scott Wickham's post
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1131769&SiteID=1

It seems you have to create your own hash variable along side the other variable:

taskHash["UserInputField"] = UserInputField.Text;
taskHash["UserInputField_ForHash"] = UserInputField.Text;
taskHash["Status"] = "Completed";
taskHash["Status_ForHash"] = "Completed";

=============================================================================
Here is a copy of the answer from Scott in the above link:
Since we're using WSS 3.0 and not MOSS 2007, we have to create and use ASP forms for any custom Workflow Task Edit pages instead of being able to use InfoPath forms (which would be nice...maybe some day we'll step up to MOSS). The custom Workflow Edit Pages are used for custom Task Content Types that we create so that our Workflow Tasks can have additional fields beyond the standard Workflow Task fields. Once you've collected the values for the Task fields from the user on the ASP Workflow Task Edit form, the typical procedure is to create a hashtable and fill the hashtable with key/value pairs that represent the names of your Task fields and their associated values, as such:

// This function is called when the user clicks the Save/Submit button
// on the Custom Task Edit ASP form
public void btnSubmit_Click(object sender, EventArgs e)
{
// Create a hashtable that will be used to update the values of task fields
Hashtable taskHash = new Hashtable();
// For each field, create two values in the hashtable. If the field name
// matches a field in the Task content type, the field name will not be
// searchable as a key within the ExtendedProperties hashtable. So
// create a second field that is a duplicate of the first but having a
// name that doesn't exactly match an existing field in the Task
// content type. That way it will be a searchable key within the
// ExtendedProperties hashtable.
taskHash["UserInputField"] = UserInputField.Text;
taskHash["UserInputField_ForHash"] = UserInputField.Text;
taskHash["Status"] = "Completed";
taskHash["Status_ForHash"] = "Completed";
// Alter the task using the vaues in the hashtable
SPWorkflowTask.AlterTask(taskListItem, taskHash, true);
// Redirect to the appropriate web page
SPUtility.Redirect(taskList.DefaultViewUrl, SPRedirectFlags.UseSource, HttpContext.Current);
}

When you make the SPWorkflowTask.AlterTask() call, the values in the hashtable are stored in the Task in the ExtendedProperties collection for the Task. That having been done, the onTaskChanged() event of your Workflow (if you have defined one for this task) will fire. If you want to access the just-changed values for this task, you will find them in the ExtendedProperties collection of the AfterProperties for the task:

private void onTaskChanged_Invoked(object sender, ExternalDataEventArgs e)
{
// The taskIsComplete boolean variable is used as the
// test for the while loop in our workflow that controls
// when we break out of the loop and move to the
// CompleteTask() step. When the value is set to
// "Complete" on the ASP form, the ASP form saves it
// in the Task and then we retrieve it here in the
// onTaskChanged() event
if (taskAfterProperties.ExtendedProperties["Status_ForHash"] == "Completed")
taskIsComplete = true;
else
taskIsComplete = false;
}

The thing to note (and the thing that caused us a lot of grief trying to figure out) is that you cannot access the field in the ExtendedProperties hashtable using the actual name of the field. This is because, for some reason, even though you store the field in the hashtable using the Name of the field as the key (e.g., "Status"), the ExtendedProperties collection actually uses the GUID of the field as the key and not the field name.

To show it visually, here are the actual contents of the hashtable from the code above (using Visual Studio debugger). The first column shows the key values for the hashtable, and the second column shows the corresponding values for each key:

ExtendedProperties Count = 10 System.Collections.Hashtable

[{53101f38-dd2e-458c-b245-0c236cc13d1a}] "DOMAIN\\swickham"
[{c15b34c3-ce7d-490a-b133-3f4de8801b76}] "Completed"
["Status_ForHash"] "Completed"
[{1c5518e2-1e99-49fe-bfc6-1a8de3ba16e2}] "ows_UserInputField_ForHash='yes' ows_Status_ForHash='Completed' "
[{f1e020bc-ba26-443f-bf2f-b68715017bbc}] "512"
[{8cbb9252-1035-4156-9c35-f54e9056c65a}] "\n \n \nTABLE.mail\n{\n..."
[{1d22ea11-1e32-424e-89ab-9fedbadb6ce1}] 155
[{4c12d635-7607-4911-a54a-7c239acdfcc3}] "yes"
["UserInputField_ForHash"] "yes"
[{4d2444c2-0e97-476c-a2a3-e9e4a9c73009}] "2007-01-19T17:10:55Z"

Notice that both values got saved for each field, but in the case of the field name for "Status", the GUID for the Status field is saved as the key and not the string "Status" that we asked it to save. Therefore, you can't retrieve the value of the Status field using "Status" as the key to the hashtable. The only time the ExtendedProperties will actually use the values you store as Field Names for the key is when the Field Names you use do not match any actual field names in the Task Content Type. That's why we use the scheme in the first block of code where we save the value of the field twice...first using the actual Field Name and the second time using a modified version of the field name that is similar enough to recognize. Then whenever we want to access the Task Field values in situations where we can get at them directly through the Field Collection (vs. through the ExtendedProperties Collection), we can use code such as:

string taskStatus = taskListItem["Status"];

And whenever we want to access the Task Field values in situations where we can't get at them directly through the Field Collection and must use the ExtendedProperties Collection, we can use code such as:

string taskStatus = taskAfterProperties.ExtendedProperties["Status_ForHash"];

and both values will be the same.

Please let us know if we're missing a much better way of doing this!

Scott
=============================================================================