locked
Completing a workflow task programmatically RRS feed

  • Question

  • I have a workflow that runs on a list and creates 3 tasks. The workflow was created using SharePoint Designer.
    I am trying to complete 2 of the three tasks programmatically and then wait until the thrid task is completed by the user.

    I have an event handler on the tasks list that is fired on ItemAdded (runs 3 times, once for each task). In the code, I determine if the item added to the task list is a task I need to approve programmatically and if it is, I attempt to do so. I set the status to "Completed" and the PercentComplete" to 100% for 2 of the 3 tasks the wait for the user. However when the user completes his/her task, the workflow on the item still shows "In Progress". The only way to get the workflow to complete is if I go back to the 2 tasks that I supposedly completed and actually complete them in the UI.

    This tells me that the way I am programmatically completing the tasks is not correct. I saw many different ways of doing this online but none worked for me. Any code I tried will actually update the task columns "Status" and "% Complete" but the actual workflow will not complete.

    This is the code that I currently have in place.

    Hashtable data = new Hashtable();
    SPListItem task = properties.ListItem;
    
    data[SPBuiltInFieldId.Completed] = "TRUE";
    data[SPBuiltInFieldId.PercentComplete] = 1;
    data[SPBuiltInFieldId.Outcome] = "Approve";
    data[SPBuiltInFieldId.TaskStatus] =
    SPResource.GetString(
       new CultureInfo((int)task.Web.Language, false),
       "WorkflowTaskStatusComplete",
       new object[0]); 
    
    SPWorkflowTask.AlterTask(task, data, true);

    Please help me out here. Thanks.
    Friday, July 31, 2009 7:58 PM

Answers

  • JohnXO,
    If you are looking to update the status of the item (on which workflow is running) then from SharePoint Designer you can set the "ApprovalStatus" to
    Approved.
    Or from C# code it will be item.ModerationInformation.Status = SPModerationStatusType.Approved

    Note that the moderation status (or ApprovalStatus in SPD)  is available only when content approval is enabled.


    You can also set the value of the workflow column by using these 2 steps:

    a) Find the name of the workflow column
    b) Set the value

    To Find the name of the column, click on the workflow column from a view, check in the URL the name of the column shown after SortField=?

    item["WorkflowColumnName"] = SPModerationStatusType.Approved;

    Please let me know the results.

    -- Mo

    Monday, August 10, 2009 9:16 PM

All replies

  • Hello
    I Have Same Problem as you.
    I change task status, task outcome, percent complete , but workflow doesn't go to the next step.

    If any one has a solution please help me.
    tanx.

    my email address: Joudy84@gmail.com

    Sunday, August 2, 2009 4:59 AM


  • Anyone at all has any ideas?????
    Monday, August 3, 2009 3:05 PM
  • I had the same issue and was able to fix it by adding the line

    data["FormData"] = SPWorkflowStatus.Completed;

    before the call to AlterTask

    Hope this helps.
    Cheers
    Carla
    Cheers Carla
    Tuesday, August 4, 2009 3:37 AM
  • John,
    You are very close to the solution. "Completed" field for Task item causes the item to complete. Please try these and exactly in the same syntax as below:

     

    task["Completed"] = true;
    task["Status"] = "Completed";
    task.Update();
    

     


    Please let me know how it goes...

    -- Mo

    • Proposed as answer by Mohan Taneja Tuesday, August 4, 2009 7:14 AM
    • Edited by Mohan Taneja Tuesday, August 4, 2009 7:26 AM Added Update( )
    • Unproposed as answer by JohnXO Tuesday, August 4, 2009 7:46 PM
    Tuesday, August 4, 2009 7:13 AM
  • Mo,

    Thanks for your reply. I tried what you suggested but I got the same results. The column "Status" in the task list was updated to the value Completed but the workflow remained "In progress". I had to go to the item in the task list and manually approve it to get the workflow to show Completed.

    This problem is definetly a show stopper.
    Tuesday, August 4, 2009 7:44 PM
  • Carla,

    Thanks for the reply but I got the same result. Workflow remains "In Progress".
    Tuesday, August 4, 2009 7:45 PM
  • Sorry John,
    I missed something above. The task object above is the reference to the task list item and not the main list/lib on which you have workflows.

    I had used this in the past and it worked successfully. Here is the snippet of code to get a list of tasks:

    SPList workflowTasks = WebSite.Lists["Workflow Tasks"];
                            SPList mainList = WebSite.Lists["Main List"];
                            SPListItem listItem = mainList.GetItemById(Convert.ToInt32(itemId));
                            SPWorkflowFilter filter = new SPWorkflowFilter();
                            filter.InclusiveFilterStates = SPWorkflowState.NotStarted | SPWorkflowState.Running;
    
    // Get a list of workflow tasks associated with current Item
                            SPWorkflowTaskCollection workTaskColle = siteColl.WorkflowManager.GetItemTasks(listItem, filter);
    
    // Here iterate thru list of tasks and find the Task item based on values
    for(.....)
    {
    //find the userTask here i.e. an object of type SPWorkflowTask from the collection 
    // workTaskColle  above
    }
    
    // using the ID of the userTask above find the SPListItem from workflow task library
    SPListItem workflowItem = workflowTasks.GetItemById(userTask.ID);
    
    and then update the tasks Completed property
    
    workflowItem ["Completed"] = true;
    workflowItem .Update( )
    
    
    Hope this helps..
    Mo
    • Proposed as answer by Mohan Taneja Wednesday, August 5, 2009 3:53 AM
    • Edited by Mohan Taneja Wednesday, August 5, 2009 3:58 AM Added more code...
    • Unproposed as answer by Mike Walsh FIN Thursday, July 7, 2011 11:11 AM
    Wednesday, August 5, 2009 3:51 AM
  • Mo,

    The last two lines of your code above are still referencing the task list item and not the main list.

    workflowItem ["Completed"] = true;
    workflowItem .Update( );
    The only difference with your code now is that you get this reference through the task list as opposed to the way I am getting the task item which is through the Tasks list event handler properties.ListItem. I tried your code nonetheless and I still got the same result.

    Take a look at my code - it is in the ItemAdded event handler of the Tasks list and that is why I am not going through the SPWorkflowTaskCollection class to get the task.

    public override void ItemAdded(SPItemEventProperties properties)
    {
       try
       {
           base.DisableEventFiring();
       
           SPListItem taskListItem = properties.ListItem;
    
           taskListItem ["Completed"] = true;
           taskListItem ["Status"] = "Completed";
           taskListItem .Update();
       }
       catch {}
       finally
       {
           base.EnableEventFiring();
       }
    }
    
    • Proposed as answer by Mohan Taneja Monday, August 10, 2009 9:04 PM
    • Unproposed as answer by Mike Walsh FIN Thursday, July 7, 2011 11:12 AM
    Monday, August 10, 2009 5:08 AM
  • JohnXO,

    That is correct. Only when the completed property of a task item is updated an event is triggered.
    The OnTaskChange event of the Task item will fire when the completed property is set.

    This is assuming there is CreateTask and OnTaskChanged (both with same correlation token / TaskId / TaskProperties) activity in the custom workflow.

    I used the same concept a day back in a custom SharePoint workflow designed/developed in C# and it works.

    In the above code why do you have taskListItem updated in itemadded event in other words as soon as a task is created, complete it? Is that for testing?
    Could you please remove the disableeventfiring and try again?

    Thanks,
    Mo


    Monday, August 10, 2009 8:54 PM
  • JohnXO,
    If you are looking to update the status of the item (on which workflow is running) then from SharePoint Designer you can set the "ApprovalStatus" to
    Approved.
    Or from C# code it will be item.ModerationInformation.Status = SPModerationStatusType.Approved

    Note that the moderation status (or ApprovalStatus in SPD)  is available only when content approval is enabled.


    You can also set the value of the workflow column by using these 2 steps:

    a) Find the name of the workflow column
    b) Set the value

    To Find the name of the column, click on the workflow column from a view, check in the URL the name of the column shown after SortField=?

    item["WorkflowColumnName"] = SPModerationStatusType.Approved;

    Please let me know the results.

    -- Mo

    Monday, August 10, 2009 9:16 PM
  • You are right it does sound a little odd that as soon as a task is created I am trying to complete it. However this is one of those workarounds that I am trying to implement due to a shortcoming in SharePoint Designer Workflows.

    I will attempt what you suggested and let you know.

    Thanks,

    Monday, August 10, 2009 11:01 PM

  • Let me clarify again - I am not trying to update the status of the list item. What I am trying to do is actually complete the workflow task inside the task item handler. I do not have a custom workflow either; just a SharePoint Designer workflow on top of a list.

    1. User adds a new item to List A
    2 SPD Workflow on List A starts and creates 3 tasks using "Collect Data from User"
    3. ItemAdded on Tasks list will fire 3 times, one for each task created.... It is here where I would like to complete 2 of the tasks

    Tuesday, August 11, 2009 3:24 PM
  • Hi All,

    Did the proposed answer work for tasks created by ""Collect Data from User"  using SharePoint Designer workflows?

    In my case I dont want the content approval to be enabled in the tasks list.

    I have around (a max of 12) reviewers in the workflow and am using SharePoint designer for workflows.

    The issue is that if one of the reviewer user is blank or empty in the action in "Collect Data from user" then a task with empty "assigned to" is created in the tasks list. The problem with this is that the primary workflow is not completed unless someone completes the empty assigned to task in the UI.

    So I am also looking into ways to complete these empty "Assigned To" tasks!

    In SharePoint designer I could check for if the reviewer is empty then not to set the collect data from user action.

    But as I have 12 reviewers I could end up creating manually more than 100 actions of "Collect Data from User" by checking whether a particular reviewer is empty or not as sharepoint designer does not allow reusing tasks :( as all tasks created using "Collect Data from User" has to have a unique task name .

    Could some please provide a workaround?

    Cheers!
    Sunday, October 18, 2009 7:30 PM
  • Hi,
    Is there a way to udate a task's Completed property in SharePoint designer?
    I can update the Status to Completed, but I can't find a way to update Completed to true. This way the workflow is stuck becuase there are situations where the task has to be completed by the workflow and not by the user.
    Thanks,
    Ami
    • Proposed as answer by warren 109 Tuesday, November 10, 2009 9:47 PM
    Sunday, November 8, 2009 9:24 PM
  • One of the things I see as missing from this conversation is the discussion of the '% Complete' on the Task Item.  You should make sure this is set to 100%.  It was my experience in the past that a failure to set this to 100% caused the Task Workflow to continue and not to complete.
    Tuesday, November 10, 2009 9:50 PM
  • You should simply

    SPWorkflowTask.AlterTask(task, data, true);
    task.Update()

    Tuesday, January 12, 2010 9:40 AM
  • Hi, i know it is a bit late ;) but anyway let me answer u so others also can gain benefit from this.

     

    in fact the field which u are trying to update is a read only field, so when u r updating the task status to 'completed' and % complete to 1.0 (100%) they are updated correctly, but if u have a look at the database table (AllUserData) where these data stored, u going to see that these field is updated except for the WorkflowOutcome field not updated so the workflow task still not completed and the workflow will not proceed to the next step.

    have a look at the workflow task list CAML and you'll find somthing like this beside the outcome field:

     

     

    
    
    <Field ID="{18E1C6FA-AE37-4102-890A-CFB0974EF494}" Name="WorkflowOutcome" 
    SourceID="http://schemas.microsoft.com/sharepoint/v3" 
    StaticName="WorkflowOutcome" Group="_Hidden" Type="Text" 
    DisplayName="Outcome" ReadOnly="TRUE" Sealed="TRUE" 
    Customization="" ColName="nvarchar9" RowOrdinal="0" />
    
    
    

     

    to get this field updated u have to update another hidden field in this list :

     

    <Field ID="{78EAE64A-F5F2-49af-B416-3247B76F46A1}"
    Name="FormData" 
    SourceID="http://schemas.microsoft.com/sharepoint/v3"
    StaticName="FormData" Group="_Hidden" Type="Note"
    DisplayName="Form Data" Hidden="TRUE" Sealed="TRUE"
    Customization="" ColName="ntext3" RowOrdinal="0" />

     

     

    the Field called FormData, just set the value of this field to Completed (in addition to the rest of task fields such as status, percent complete) and then outcome field will be updated and workflow will proceed to the next step.

     

    what happened here is that when you updated the task details to completed without updating this field it considered to be saved as draft, but when u update this field it is equal to that u pressed complete task.

     

    hope this will help.

     

    Thank you,

     

    Tarek Jajeh

     

     

    Wednesday, March 24, 2010 1:05 PM
  • Thank you. I tried this, add "<my:FormData>"+"Completed"+"</my:FormData>" to my XmlDocument in workflow.AlertToDo(item,taskID,guid,XmlDocument);

    and it really work and the task go to next step.

     

    By the way, when I use workflow which is not designed by sp Designer, the "FroData" node is not necessary.

    Thursday, July 7, 2011 2:19 AM