How do you close tasks that are created inside a replicator?
Hi,
I create an unkown number of tasks within a replicator. Now at a later state I wish to complete all tasks that were created in the replicator.
But when I try to set the CorrelationToken on the CompleteTask activity outside the replicator I cannot see the tokens assigned to the tasks created in the replicator shape.
And ideas on how to do this?
Thanks
[383 byte] By [
GR101] at [2008-1-2]
Just off the top of my head, but could you use an 'UpdateAllTasks' activity to set the completion field? I mean, I can see problems with that (what happens if you have other tasks open at the same time, for example) and it's a bit inelegant, but it might work.
Solved it.
I had to use custom code in a Code activity. The cool thing about this is that it does not require correlation tokens.
Here's what I did:
1) in the CreateTask activity (createTask1) I store the TaskID guid value in a local variable (seqOfEventsTaskGUIDs)
2) later on in the workflow (when we need to complete the tasks created above) I loop through the task items in SharePoint looking to see if it's contained in seqOfEventsTaskGUIDs. If it is then I close it.
Below is the code that is used in Step 2.
// Find tasks and set them as Complete
XmlDocument xmldoc = new XmlDocument();
SPWeb web = new SPSite(workflowProperties.SiteUrl).OpenWeb();
SPList list = web.Lists[workflowProperties.TaskListId];
for (int i = 0; i < list.ItemCount; i++)
{
SPListItem item = list.Items
;
xmldoc.LoadXml(item.Xml);
string itemGUID = xmldoc.FirstChild.Attributes["ows_GUID"].Value.ToLower();
// find Sequence of Events Task
if (seqOfEventsTaskGUIDs.Contains(itemGUID))
{
// Complete Task
item["Status"] = "Complete";
item.Update();
}
}
It's a bit of a mission but dont know of any other way to do it. If someone knows of one please add to this post.
Actually UpdateAllTasks will work for every task that is not compleated so in a case wher eyou need to close the remaining tasks you can use the UpdateAllTasks activity (using the workflow correlation token) and then apply the follwing code.
private void UpdateAllTasks(object sender, EventArgs e)
{
updateAllTasks_TaskProperties.PercentComplete = 1.0f;
updateAllTasks_TaskProperties.ExtendedProperties["Status"] = "Cancelled";
}
Hi,
I'm trying to do the same thing and was wondering if you had any further info. My scenario is similar to the collect feedback sample (one tasks gets assigned to multiple users via a replicator) except that I would like just one person to have to complete the task (i.e. all others should be closed when this happens. I tried to use the code you provided but it didn't seem to work, as the only place I could put it was inside the replicator and when it executed, I got an exception saying that the task was locked, and thus could not be modified. Do you know if there is a way to use the closetask activity to do this?
Thanks in advance,
VJ
Hi,
May I know how do you implement the steps 2(later on in the workflow..)?
Thanks.
Sorry for the delayed reply I've been off this stuff for while.
I implemented Step 2 by putting it inside a 'CodeActivity' object so I did the following:
- Drag a Code Activity object onto the canvas (this was after a OnWorkflowItemChanged event)
- right click on the canvas and select 'View Code'
- create a new function like the following
private void closeAllTasks_ExecuteCode(object sender, EventArgs e)
- Copy the code that I pasted above in Step 2 into this function
- Go back to the canvas and select the CodeActivity that was created above.
- On the CodeActivity set the 'ExecuteCode' property in the properties box (F4) to
closeAllTasks_ExecuteCode
I use a Replicator of WssTaskActivities (from the ECM Starter Kit) inside a ConditionedActivityGroup that is also running a "MonitorAndEnforceDueDate" DelayActivity.
The CAG has an UntilCondition (rule-based, this.StopTheCAG == true).
Neither the Replicator nor the DelayActivity have When conditions, so the CAG runs them only once (which, when you think about it, is what is needed).
Basically one of two things happens to escape from the CAG:
1. All the WssTaskActivity's created by the Replicator finish "normally", in which case the OnReplicatorCompleted method sets StopTheCAG to TRUE, causing the DelayActivity to be cancelled.
2. The Due Date[/Time] occurs, in which case I call my HandleAnyOverDueTasks method which locates any Tasks that are (a) not deleted (WssTaskActivity.IsTaskDeleted == false) and (b) have a Percent Complete < 1.0f or Status <> Completed. Inside that loop, I match up the WssTaskActivity with the corresponding SPWorkflowTask, set up a hashtable with Status and my special OverDue,"false" key/value pair that get passed along with the SPWorkflowTask to AlterTask. Those in turn auto-magically calls the IsTaskCompleted method, passing the hashtable as AfterProperties (WssTaskActivity intercepts OnTaskChanged and only calls your IsTaskCompleted method). Inside IsTaskCompleted, I react to the presence of AfterProperties
key/value pair OverDue by setting the Task Outcome to "auto-completed, overdue task". Then I set the StopTheCAG value to TRUE.
The end result is, I have complete control over how any remaining replicator-created tasks (WssTaskActivity) are handled when the (common to all tasks) due date arrives. If I didn't use the AlterTask technique in the non-replicator part of the CAG and simply set StopTheCAG to TRUE, the remaining tasks would be canceled, but not in a way that I can control.