Step by Step Tutorial. Creating Workflows for Windows Sharepoint Services and MOSS2007 (part 6/20)




By Serge Luca

MVP Windows Workflow Foundation 


Step 6/20.Using Several Task Forms

Download the code


Even if it’s not the best choice here, imagine that we  split the approve/reject process in 2 tasks : an approving task and a rejecting task: this means having 2 tasks forms and refactoring the workflow to make it listening to 2 possible events (the manager did approve or the manager did reject).


Make a copy of the existing Infopath form and rename it Reject.xsn.

Rename the original form to Accept.xsn.

Design reject.xsn , change the header and remove the accept button:


Go to the Fileproperties menu and change the form id:



Publish the form as we did in the previous step,  but here rename the Form template  to Reject and the form template file to Reject.xsn :


Remember to keep the textbox empty in the next step…

Design Approve.xsn and remove the Reject button:


Publish this form as we did for the Reject form , but the form template should be Approve and the file Approve.xsn.

Copy both published files to your project folder.

Drag and drop a ParallelActivity after the requestManagerApproval activity and rename the activities as follows:


Move the ApproveRejectTask to the left branch of the ParallelActivity and drag & drop another CreateTask activity to the right branch.Rename these activities respectively  approveTask and rejectTask;  set their correlation token to ApproveToken and RejectToken and their invoked method to ApproveTask_MethodInvoking and to RejectTask_MethodInvoking:



Note: using a ParallelActivity is not strictly necessary here, we could have put the approveTask and the rejectTask activities in a sequence.

Now we need to listen to the manager’s decision : 2 events could be sent:  approved or rejected; the usual pattern for handling this  in Workflow Foundation is to use a ListenActivity:

Drag and drop a ListenActivity just after the ParallelActivity and move the WaitForApprovalRejection and the ApproveRejectTaskCompletete to its left branch; make a copy these activities to the right branch.

·         Rename WaitForApprovalRejection to onTaskApprovalChanged.

·         Rename onTaskChanged1 to onTaskRejectionChanged.

·         Rename ApproveRejectTaskComplete to approveTaskComplete.

·         Rename completeTask1 to rejecteTaskComplete.

·         Rename the ListenActivity to WaitForManager

·         Rename the left branch to WaitForApproval and the right branch to waitForRejection


Set the Invoked property of onTaskApprovalChanged to a new event handler : WaitForApprovalTask_Invoked.

Set the Invoked property of onTaskRejectionChanged to a new event handler: WaitForRejectionTask_Invoked.

We now have to change the correlation token : the left branch activities will be correlated with ApproveToken and the right branch activities with RejectToken.

Changing the taskId

The activities on each branch must use the same taskID : we need to create 2 new taskId : ApproveTaskId and RejectTaskId at the level of respectively approveTask and rejectTask activities (taskId property –Bind to a new memberCreate field).

Set the taskId property of the left branch activities to approveTaskId and to rejectTaskId for the right branch activities.


Changing the TaskProperties

Since we’ll have 2 tasks, we need to stored the tasks data in 2 news TaskProperties ; bind the Taskproperties property of the approveTask and rejectTask activities to 2 new taskproperties field members : ApprovedTaskProperties and  RejectTaskProperties


Changing the TaskProperties

Since we’ll have 2 tasks, we need to stored the tasks data in 2 news TaskProperties ; bind the Taskproperties property of the approveTask and rejectTask activities to 2 new TaskProperties field members : ApprovedTaskProperties and  RejectTaskProperties .

Changing the AfterProperties

Bind the Afterproperties property of onTaskApprovalChanged and onTaskRejectionChangedand 2 new TaskProperties field members : AfterApprovProps  and AfterRejectProps.

Set the task Guid, task form and task properties

Code the invoking methods as follows:

        private void RejectTask_MethodInvoking(object sender, EventArgs e)
            this.RejectTaskId = Guid.NewGuid();
            this.RejectTaskProperties.Title = "Reject this expense report";
            this.RejectTaskProperties.AssignedTo = Manager;
            this.rejectTask.TaskProperties.TaskType = 1;
        private void ApproveTask_MethodInvoking(object sender, EventArgs e)
            this.ApproveTaskId = Guid.NewGuid();
            this.ApprovedTaskProperties.Title = "Approve this expense report";
            this.ApprovedTaskProperties.AssignedTo = Manager;
            this.approveTask.TaskProperties.TaskType = 0;

The TaskType property will be used to link the forms to the appropriate tasks.

Let’s modify the workflow.xml file :modify the task0_FormURN to the approval form template Id and add define a new task form (task1_FormURN) for the rejection form .


Double click on the onTaskApprovalChanged and on the onTaskRejectionChanged activities and set their event handler as follows:

       private void onTaskApprovalChanged_Invoked (object sender, ExternalDataEventArgs e)
            string acceptedRejectedStatus =
            this.WorkflowProperties.Item["Status"] = acceptedRejectedStatus;
        private void onTaskRejectionChanged_Invoked (object sender, ExternalDataEventArgs e)
            string acceptedRejectedStatus =
                this. AfterRejectProps.
            this.WorkflowProperties.Item["Status"] = acceptedRejectedStatus;

We need to improve the workflow design: indeed 2 tasks (Approve and Reject) will be created, and the manager can only perform one of them: for instance, if the manager approves the expense report, then the reject task should automatically be deleted.

Drag and drop 2 delete DeleteTask activities at the end of each branch of the ListenActivity:

Rename the DeleteTask of the left branch to deleteRejectionTask an and bind its TaskId property to the existing field RejectTaskId; set its correlationToken to RejectToken.

Rename the DeleteTask of the right branch to deleteApprovalTask an and bind its TaskId property to the existing field ApproveTaskId set its correlationToken to ApproveToken.


The following picture illustrates a important part of the workflow  left branch:


Build the solution, call install.bat and test the workflow;  you’ll notice that 2 tasks have been created; if you select the reject task and if you click on the reject button in the form, then the Approve task will be removed and vice-versa.

This hands-on training is the property of Redwood S.L sprl and may not be organized in class or in group without the prior written permission of Serge Luca. Should you wish to organize this hands-on training in your company or institution, please contact Serge Luca  first to enter into a licence agreement. Each trainer or teacher using this hands-on training should have a licence agreement. Please ask your trainer or Serge Luca whether he or she has entered into a licence agreement with Redwood S.L sprl.

The hyperlink to this hands-on training may be placed on your website for free, on the condition that the name Serge Luca is clearly mentioned in the reference. Please send us a mail containing the link to the web page our reference is used on.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s