Hi
Most activities in my workflows are human activities and are therefore event-driven. The workflow blocks at each new activity waiting for a user to click "Complete" or "Approve" in the application GUI. These activities have a number of common business-logic properties, encapsulated in a custom base class. Example properties are: TargetCompletionTime, Priority, RequiresApproval etc. The values of these properties are tracked using TrackingExtracts and custom TrackingProfiles. This allows me to query the tracking service for the current state of my activities, including the values of the custom properties.
The complication is that I need to be allow my users to update the values of these activity properties at any time without closing the Activity. For example an administrator must be able to edit any current or future activity and change the priority, target time or assigned user. These changes need to be tracked so that the latest values can be shown to the executor of the activity.
I have been trying to do this via a parallel activity and external data exchange services. The parallel activity has one branch waiting in a loop for the update event on a subclass of HandleExternalEvent and the other branch waiting for the completion event on a 2nd HandleExternalEvent subclass (these two events are on different service interfaces). The update branch loops as it should not close the activity after an update. Does this sound reasonable I had looked at the Listen activity for this but I think this is unsuitable as a message sent to the "update branch" will cause the parent Listen activity to complete. I also have not been able to work out how I can send messages to the Update interface before the activity enters a wait state e.g. when it is a future activity.
I feel I must be missing a basic pattern for this very simple problem - my approach seems to need a lot of plumbing to just change the properties of a running activity. Considering this effort alongside the restrictions on inheriting from a composite activity and the complexities of tracking, and I am seriously starting to think it would be easier to store my custom activity state in my application database and only use WF to guide the activity flow.
Any suggestions on better ways of addressing what must be a very common task would be much appreciated.

Pattern for updating custom Activity Properties without completing Activity
Dave Auld
Thanks for the clarification.
One problem I encountered with this approach is with inheriting from the base workflow: I have an inheritance hierarchy of workflow classes, with the base workflow inheriting from SequentialWorkflowActivity. This BaseWorkflow class contains properties like DisplayName, custom status flags etc. that are common to all my workflows. The workflow inheritance hierarchy is several levels deep e.g.:
BaseWorkflow : SequentialWorkflowActivity
WorkflowType1: BaseWorkflow
WorkflowType2 : BaseWorkflow
WorkflowType3 : WorkflowType2
Additionally, some of these derived workflow types are used as base types for XOML workflows.
If I add an EventHandlingScopeActivity to the BaseWorkflow as the sole child activity (containing in turn an empty SequenceActivity as parent for the actual workflow) then this BaseWorkflow becomes a black-boxed custom composite activity and I can no longer inherit from it and still add child activities. This is identical to the problem I asked about here:
http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=813174&SiteID=1
The only solution here seems to be not adding a custom EventHandlingScopeActivity to the BaseWorkflow, but instead duplicating it across all my derived workflow classes. But this would still only allow a workflow inheritance hierarchy only one level deep (so WorkflowType3 : WorkflowType2 would not work as WorkflowType2 would be a composite). As I asked in my other post, am I missing some basic technique for reusing composites across derived activities and workflows
Caesar Samsi - MSFT
I meant option 2. Good catch, and sorry for the lack of detail.
-Angel
Martinp23
OK, this is starting to become clear. Apologies for splitting the discussion into two posts, it wasn't clear at first that they were about the same problem.
The first issue was trying to work with an inheritance hierarchy of workflows greater than one level deep:
1) BaseWorkflow : SequentialWorkflowActivity
2) WorkflowType1: BaseWorkflow
3) WorkflowType2 : BaseWorkflow
4) WorkflowType3 : WorkflowType2
I did not mention is that with the exception of WorkflowType3, all of these workflows are empty, "abstract" workflows without children: they differ only in their property declarations. In addition to the above workflow types I also have something like:
4) ConcreteWorkflow1 : WorkflowType1
5) ConcreteWorkflow2 : WorkflowType2
These 2 concrete workflows are where the activities are added. This hierarchy really exists only to add new properties to more specialised workflow types. E.g. BaseWorkflow contains a DisplayName property. WorkflowType1 is then the base for my user-created XOML workflows, and so it has a CreatedBy, CreatedDate properties. WorkflowType2 is the base for precompiled workflows which map to a documented business process and so it has a BusinessProcessReference property etc. Only the most derived workflow types contain any activities. Up till now I had had no problems with this as all the super classes were empty of child activities, it was only the addition of the EventHandlingScopeActivity to the base class that brought me up against the composite inheritance limitation.
I see that this cannot work in WF: of course an activity graph is not overridable or extendable in a meaningful way. Although I wasn't actually trying to do this with my workflow hierarchy, it wasn't clear to me at first why it should be so difficult. Your statement that "this is the equivalent of deriving from a .NET class with a Main() method and changing the logic inside of there" helped switch the lights on in this regard. BTW, I notice a lot of other forum posts about the same or related problems. It would be helpful to make the reasons for the blackbox/inheritance limitation clearer in the documentation on implementing custom activities, along with the workarounds.
My second, related problem was with reuse of custom composite activities like the EventHandlingScopeActivity. In all reuse cases I was trying to define some common base behaviour while leaving an empty sequence where children could be added. ToolBoxItem seems to be the way of dealing with this for both workflows and custom activities.
Can you point me at some samples or documentation of this ToolBoxItem approach There is a brief mention on the "Using Composite Activities" MSDN page (http://windowssdk.msdn.microsoft.com/en-us/library/ms734576.aspx) but I can't find any examples of inheriting ActivityToolboxItem in the SDK samples or labs.
Thanks once again for your help, I may now actually be able to get some work done with WF :)
mm123
I have another question about this approach:
Using this technique, is there any way I can send an Update message to a specific, named future activity HandleExternalEvent always addresses the current waiting activity as far as I can see, but my sysadmins need to be able to select a future activity from a diagram/activity list and change some of its instance property values before it becomes active. I can't find any samples or documentation on sending an event to a specific, possibly non-active activity (past activities will not be updated in my application). I realise addressing a specific named activity in this way would be complicated by spawned contexts in loops etc., although in my case changing the properties for all spawned instances of an activity would suffice.
Thanks in advance.
J_Dude2003
That sounds like a good solution. Can you clarify one thing: when you say "make your root activity an EventHandlingScope" do you mean:
(1) I should change the base class of my workflows from SequentialWorkflowActivity to EventHandlingScopeActivity, or
(2) that the parent SequentialWorkflowActivity should contain an EventHandlingScopeActivity as its first child, with all other activities within it
If you mean option (1) and my workflow root activity is an EventHandlingScopeActivity instead of an SequentialWorkflowActivity, will the consequence not be a loss of important SequentialWorkflowActivity functionality like the public DynamicUpdateCondition property and the Completed/Initialized EventHandlers
seprice
Thx again
Ljhopkins
You can send messages for HandleExternalEvent activities that are not yet executing and they will be placed in a corresponding queue. They will not be received by the activity until it is executing though, so this will not address your needs.
One way you could achieve this is to make your root activity an EventHandlingScope. You can have a workflow-level event handler with a HandleExternalEvent activity that listens for a special event (e.g. UpdateActivity) that is triggered when your sysadmin selects an activity to update from their end. This message will contain the information needed to look this activity up (mainly the Name) and information about the update (maybe a dictionary keyed on property names). When this message is received, you can look up the corresponding activity and apply updates all from within the workflow. Since you're in the workflow, you'll have full information and access to the entire workflow and its state.
Hope this helps.
-Angel
PeterVrenken
Why don't you give this a shot:
EventHandlingScopeActivity
HandleExternalEvent (completion event)
EventHandlersActivity
EventDrivenActivity
HandleExternalEvent (update event)
The above workflow snippet leverages the EventHandlingScopeActivity. The way this activity works is that it has a main body that consists of one activity, which begins executing immediately, and an optional EventHandlersActivity child, that can contain one or more EventDriven activities. If EventDriven activities are specified, then these events will be listened for in parallel to the executing body, and can be received over and over as long as the main body is not complete.
So in your scenario, you will have a HandleExternalEventActivity in the main body that is blocking, waiting to receive the completion event. In parallel though, you will have another HandleExternalEventActivity sitting in an EventDrivenActivity receiving and processing update events over and over until the completion event arrives and the whole thing is done executing.
Does this address your desired pattern
Thanks!
Angel
Ron L
Hi Angel,
For the workflow snippet you layed out:
EventHandlingScopeActivity
HandleExternalEvent (completion event)
EventHandlersActivity
EventDrivenActivity
HandleExternalEvent (update event)
can this be achieved in sequential workflow
If so can you possibly desribe which workflow toolbox items to leverage in the designer
Thanks.
Radioedit420
Let me enumerate your scenarios in order to organize my comments.
1) BaseWorkflow : SequentialWorkflowActivity
2) WorkflowType1: BaseWorkflow
3) WorkflowType2 : BaseWorkflow
4) WorkflowType3 : WorkflowType2
Scenario 1: This makes perfect sense. You need some custom state / code in your base workflow. It's essentially a customized "canvas", but has no children.
Scenario 2: Using your empty base workflow and filling it in - cool.
Scenario 3: A different workflow that leverages the same base class logic - cool.
Scenario 4: This doesn't make much sense to me. You're trying to derive from a workflow with intentions on modifying its definition. This is the equivalent of deriving from a .NET class with a Main() method and changing the logic inside of there. Do you see how this doesn't make sense logically
WorkflowType3 may be very close in its implementation to WorkflowType2, but it is indeed a different workflow. That's why I'm saying that if your variations have many commonalities, your best bet is to have the right toolset of custom activities so that your users can compose these workflows from scratch quickly and easily. Essentially, creating WorkflowType2 and 3 from scratch (inheriting each from BaseWorkflow) should be easy to accomplish using your provided custom activities that handle the complex stuff (Listens, Parallels, etc.).
As for the EventHandlingScope, this is something that will be common to all workflows that derive from BaseWorkflow. The right way to do this is to create a custom ToolBoxItem component for BaseWorkflow that will automatically add an EventHandlingScope to the workflow upon initialization on the design surface. This is the mechanism that ParallelActivity uses to end up with two Sequences whenever you drop it into a workflow - they're not actually compiled into the Parallel (or Parallel would be a black box activity).
I know this is a lot of information at once, but hopefully it is helpful.
Thanks,
Angel