ecently I started working with a client who was interested in using Windows Workflow Foundation (WF) in a custom application. Having never used WF before, I thought it might be interesting to document the experience and my assumptions as I started learning and implementing the technology in production.
I talked extensively to the client, and took copious notes on the client’s business rules to develop a general feel for how a workflow might make sense in the context of the application. Later, I went back to my desk and created some clean, crisp Visio diagrams with processes and decision branches and many lines and arrows. Quite satisfied with myself, I showed this to the client. After we discussed and tweaked the flow of the diagram, we reached an agreement on the details and I went back to my desk, ready to start on my first workflow.
At this point I ran headlong into my first brick wall.
The Workflow Designer Is Not Visio
The sooner you accept this fact, the easier your life will be?or at the very least, you will have slightly more realistic expectations. No matter how pretty you make your process flowcharts and diagrams in Visio, they will bear little or no resemblance to what you end up with in the Workflow Designer.
In fact, you can do a number of things in Visio that you simply can’t do in the Workflow Designer, such as controlling the placement and visual flow of your workflow activities. Take a look at Figure 1 and Figure 2 to see what I mean.
After recovering from the initial shock of seeing my beautiful workflow rendered as something less aesthetically pleasing, I went through the diagram one activity at a time and proceeded to start giving everything meaningful names. Some activities would require code, while others were merely conditional branches and terminators, so I gave them all easily readable and recognizable names. To simplify tracking, I gave the code activities the same name as their code behind routines. Some of my if/else activities shared a name with another activity (unintentionally.)
At the end of the day, I saved everything and went home, pleased with my progress. I didn’t bother doing a build at this point, because I hadn’t actually written any code, and the designer hadn’t complained about anything.
The very next morning, I learned my second Windows Workflow lesson.
What’s in a Name?
As it turns out, there’s quite a bit in names, apparently. The workflow designer will let you use the same name in several different places (activities, properties, methods, etc.) without complaining. You’ll get errors at build time, but by then it could be a huge mess to untangle.
One example of where this can really get you in trouble is when you give a code activity the same name as the code behind method that it executes.
This is a perfect illustration of why naming conventions are useful. For example, you could prefix your code activities with “ca” to differentiate them from the code behind methods they call.
Visual Studio also provides a Generate Handlers link in each activity’s property sheet. Selecting an activity and then clicking this link generates the most likely event handler in the code behind file. However, some of the names it generates are less than elegant. Of course you’re free to change the names and remap the activity, via the property sheet?but that’s exactly how I got myself in trouble and learned my third Windows Workflow lesson.
|Editor’s Note: This article was first published in the March/April 2009 issue of CoDe Magazine, and is reprinted here by permission.|
Workflow Designs Can Vanish
After coming back the next day and reopening my workflow, or rather trying to reopen it, I discovered that when things in the code behind file don’t make sense, the Workflow Designer can’t (and won’t) try to clean up your mess. Instead, you get a nice screen that looks like Figure 3.
|Figure 3. An Informative WF Error Message: Unhelpfully, WF lets you know that there’s an invalid object reference somewhere in your workflow.|
If you see that screen, put your scuba gear on, because you’re going code diving. The most likely culprit is that you have a duplicate name somewhere, and you’ll have to dig through the WorkflowName.cs and WorkflowName.Designer.cs files to clean up the problem.
Occasionally, your workflow might vanish for other reasons?even if you’ve done everything right.
If that happens, here are two remedies you can try. One way is to right-click on the solution name in the Solution Explorer window and then click “Clean Solution” on the context menu. Click on a tab other than your workflow diagram, and then click back to the designer. That often solves the problem; however, if it fails, restart Visual Studio. If your workflow has no other problems, one or both procedures will usually fix the problem.
While I was untangling my mess, it occurred to me that cleaning it up sure would be easier if I had broken the workflow into custom activities during the design phase. I decided that as long as I was cleaning things up anyhow, it made sense to go ahead and put the various pieces into separate activities (think Custom Controls in Windows Forms.) Coincidentally, this brings me to the fourth Windows Workflow lesson.
Custom Activities Are Your Friends
It’s true. Custom Activities are your friends. They may not always act like your friends, and sometimes they may borrow your stuff without asking, never bring it back and claim it was theirs all along, but ultimately they are your friends.
You should create custom activities whenever it makes sense to do so, either because you intend to reuse an activity in other areas of a larger workflow, other workflows, or just because it helps to break up a much larger workflow (allowing multiple people to work on different areas at once).
To create a custom activity, right-click in Solution Explorer and select Add, then select Activity. I usually create a folder to store all of my custom activities.
Separating workflows into custom activities make maintenance significantly easier and also help to alleviate naming conflicts between similar or identical activities in different parts of the workflow.
No surprise, this brings me to the fifth Windows Workflow lesson.
Some Workflows Require Identical Activities in Multiple Places
One of the great things about Visio is that you can route your “flow” however you like, even if that involves hitting the same activity from different paths. Unfortunately, you can’t hit the same activity from multiple paths in a workflow, so you have two choices:
- Duplicate activities in your workflow (with different names of course)
- Create a custom activity with the necessary functionality and add multiple instances of that activity to your workflow.
If you can accomplish this with a custom activity, you should do so unless the item is just too small to warrant the effort, such as when the activity has only one step. Again, be sensitive to your activity names, because having two code activities (for example) with the same name will cause you pain later. Depending on how far along you are, you’ll have a fun time untangling which activity is which when the Workflow Designer goes bye-bye.
After cleaning up the naming mess and breaking my large workflow into smaller logical pieces, it was time to get back to the business of making my workflow actually flow. I took a look at the various conditional branches in my workflow and added some Boolean flags in the code behind file. With those in place, I began writing rules for the If/Else activities. Within a few minutes I had a nice collection of rules that covered every if and every else in the entire collection of workflows?but something still didn’t seem quite right.
That brings up Windows Workflow lesson number six.
They’re Called If/Else Activities for a Reason
To work with an If/Else activity, you give it a name and description (optional), and that’s it. All the real functionality goes into the If/Else branch activities created within the parent container.
You can use this activity in a few ways. If all you need is the standard If/Else construct, then add a condition to the first branch.
|Author’s Note: Typically this is the left branch, but you won’t have any trouble spotting it, because you’ll see a red circle icon containing a white exclamation mark at the top right corner. These red and white icons indicate tasks you must take before your workflow will build; so be sure to pay attention to them.|
To add a condition, click the activity and look at the property sheet. You will see a Condition property with the now familiar red and white icon. If you click the dropdown list, you will see two available options: “Code Condition” and “Declarative Rule Condition.”
Selecting the Declarative Rule Condition adds a couple of extra properties to the sheet and moves the error icon to the next step you need to complete. Clicking the ellipses next to the ConditionName property displays the Rule Condition Editor (see Figure 4).
|Figure 4. The Rule Condition Editor: You assign rule conditions in this built-in editor, which provides IntelliSense assistance.|
The Workflow Rule Editor provides useful IntelliSense for rule writing. After writing a rule for the first branch and close the editor, you’ll notice the error icon has finally disappeared (for that activity).
Interestingly, there is rarely a valid reason to write rules/conditions for the Else part of If/Else activities. If you need multiple branches, similar to a Select Case or Switch statement, you can add a branch by clicking on the parent If/Else activity and then clicking “Add Branch” in the property sheet. Alternatively, you can drag another If/Else activity into your Else branch, depending on which one makes the most sense for the workflow.
Typically though, you should avoid adding rules or conditions to the Else branch. Note that the designer doesn’t display the error icon for that branch, even though it is empty. Adding conditions to this branch is not good practice, because it hides flow logic and could cause problems later on. Usually, if you think you need a condition on your Else branch, chances are what you really need is another branch or another If/Else activity in that part of the flow.
Eventually I got the conditional branches all sorted out, which made me realize there were a few different ways out of my workflow. Depending on the specific conditions, certain branches of the workflow might never execute. This brought me to the seventh Windows Workflow lesson.
Use “Terminate” Activities (Even If You Don’t Think You Need Them)
When you’re designing your workflow, it’s easy to think “I don’t need to terminate this section. It just flows right out to the end anyway.” Maybe that’s true, but what if your workflow gets incorporated into a different workflow, or gets modified after you’ve started working on something else?
Terminate activities give you a chance to leave a comment about why you’re terminating the flow in that specific spot. They also let you generate an error message if needed, and prevent the workflow from accidentally continuing forward if someone adds more activities between your de facto termination point and the actual end of the workflow.
|Author’s Note: Using a Terminate activity in your workflow results in a WorkflowTerminated event rather than WorkflowComplete event, so make sure you process it accordingly.|
While wrapping up the design, I decided that it would make more sense to just add the workflow files to an existing project rather than having a separate workflow project. That brings me to the eighth and final (for now) Windows Workflow lesson.
Some Things Are Better Left Alone
I added the existing files to my class library project and did a quick build, no errors. So far so good, so I thought. After the build finished, I continued working and realized that I needed to go back into the workflow designer to make a small change.
Unfortunately, at this point I discovered that the Workflow Designer wouldn’t load. Instead I got a rather cryptic error informing me that “the service ‘System.Workflow.ComponentModel.Design.IIdentifierCreationService’ must be installed for this operation to succeed.”
A quick Live Search for the error led me to the MSDN forums for Windows Workflow Foundation, which in turn revealed that adding workflows and activities to a non-workflow project is not supported. Fortunately, it was a trivial exercise to get everything back in order and in its own project again.
Try It for Yourself
Hopefully these “lessons” will prove useful to you (or at least my mistakes may serve as a warning) as you begin your own personal journey into the world of Windows Workflow Foundation.