Custom Workflows With Office System Server 2007
It hasn't been the easiest thing to figure out but I'm awfully happy to say that I've finally got a near fully functional complete custom workflow via Visual Studio 2005. One of the key points to remember is that “Nothing Is Magic” with this thing. There are a few issues in doing this workflow development that hopefully are my pure ignorance (and/or lack of documentation).
Deployment of these workflows isn't the easiest thing. It has taken me awhile of editing the default “Install.BAT” and trial and error to actually get the workflow (once customized beyond the HelloWordSequential example) installed correctly with everything in all the right places. It also appears that I have to reinitiate the workflow after every build. I foresee this being a huge problem in production. I am hopeful that I'm simply missing something but if I tag a library with my workflow and call it “My Righteous Workflow.” I make a change to the workflow, rebuild, run install.bat to update everything. My original “My Righteous Workflow” doesn't work and, morever, doesn't update. I have found I have to remove the first instance of the workflow and the retag the library with the new instance of the workflow. Or I can disable new instances of the old workflow and add the workflow again. I can see this getting a little hairy with scope creep. We all know that you start one project and 5 months later it's a monster the likes of which you never imagined.
One of my largest problems was actually updating the initial list item. Essentially I created a Form Library list. I created an InfoPath form (running in the web browser, of course) as my content type. The initial content type requires a few pieces of information. Once the new item is created, the workflow is automatically kicked off. Two new tasks are created asking two separate individuals for additional information (using Infopath forms again). Once they've submitted the data, the original list item needs to get updated with that data. It's really pretty easy but I guess I was thinking that the workflowProperties object has the Item in it and that I could just update that Item but you can't. You actually have to tag the item manually and run the update method on it. The workflowProperties object gives you everything you need in order to do this very easily:
SPWeb thisWeb = new SPSite(workflowProperties.SiteId).OpenWeb(workflowProperties.WebId);
SPListItem thisItem = thisWeb.Lists[workflowProperties.ListId].GetItemById(workflowProperties.ItemId);
thisItem.Properties["myFirstProperty"] = netTaskAfterProperties.ExtendedProperties["firstProperty"];
thisItem.Properties["mySecondProperty"] = netTaskAfterProperties.ExtendedProperties["secondProperty"];
thisItem.Properties["myThirdProperty"] = netTaskAfterProperties.ExtendedProperties["thirdProperty"];
thisItem.Update();
Using InfoPath forms for each stage of your workflow is pretty easy too. You simply create the InfoPath form, add it to your workflow.xml file and then make sure you set the TaskType property accordingly for each stage. Stages can share InfoPath forms too.
Here's an excerpt from my workflow.xml file:
<MetaData>
<Task0_FormURN>urn:schemas-microsoft-com:office:infopath:New-Hire-Office-Manager-Initiation:-myXSD-2006-05-26T17-29-20</Task0_FormURN>
<Task1_FormURN>urn:schemas-microsoft-com:office:infopath:NewHireCommInitiation:-myXSD-2006-05-26T17-29-20</Task1_FormURN>
<Task2_FormURN>urn:schemas-microsoft-com:office:infopath:NewHireNetworkInitiation:-myXSD-2006-05-26T17-29-20</Task2_FormURN>
<Task3_FormURN>urn:schemas-microsoft-com:office:infopath:NewHireCompletionTask:-myXSD-2006-05-26T17-29-20</Task3_FormURN>
<Task4_FormURN>urn:schemas-microsoft-com:office:infopath:NewHireBillingInitiation:-myXSD-2006-05-26T17-29-20</Task4_FormURN>
<Task5_FormURN>urn:schemas-microsoft-com:office:infopath:NewHireSendBillingTask:-myXSD-2006-05-26T17-29-20</Task5_FormURN>
....
</MetaData>
I actually have a lot of tasks in my workflow at the moment but a few of those tasks use the same form and as a result I set the task properties TaskType for each of those tasks to the same number as so:
myFirstTaskID = Guid.NewGuid();
myFirstTaskProperties.TaskType = 0;
....
myFifthTaskID = Guid.NewGuid();
myFifthTaskProperties.TaskType = 4;
mySixthTaskID = Guid.NewGuid();
mySixthTaskProperties.TaskType = 4;
mySeventhTaskID = Guid.NewGuid();
mySeventhTaskProperties.TaskType = 5;
Clearly these variable names are for purposes of this post but I hope you get the picture. It's also very easy to pass data into those InfoPath forms. Here I have passed in the value of the “Floor“ column from the original list item into one of my InfoPath task forms.
myFirstTaskProperties.ExtendedProperties["Floor"] = workflowProperties.Item.Properties["Floor"];
The other half of this task is to create an ItemMetadata.xml file containing the fields you will be passing in and using it as a data connection in the InfoPath form.
I hope this post sheds some light on how to get custom workflows moving... it's quite an exciting feature. I'm hoping there is an easier method for deploying from your dev environment to a production or staging environment ...