none
Approve Workflow Task Programatically

    Question

  • Overview:
    I am trying to approve a task programatically using either SharePoint Web Services or Client Object Model. I can update the task properties but the workflow doens't move to the next step.

    Details:
    I have created a list and associated a simple SharePoint 2010 approval workflow with it. The workflow is simple, just approve the task from 2 users one at a time.
    When I create an item in the list and start the workflow, a task is created and I can approve it manually. After it is approved by the first user, it goes to the second one. After being approved by the second user, the workflow is completed.
    Programatically, I can access the task and change some of its properties but the workflow never moves to the next step.

    Using Web Services:
    I am calling UpdateListItems method of Lists.asmx

    batchElement.InnerXml = "<Method ID='1' Cmd='Update'>" // Also tried Cmd='Moderate' but I believe it is giving the same result
                    + "<Field Name='ID'>115</Field>"
                    + "<Field Name='Status'>Completed</Field>"
                    + "<Field Name='FormData'>Completed</Field>"
                    + "<Field Name='WorkflowOutcome'>Approved</Field>"
                    + "<Field Name='Completed'>True</Field>"
                    + "<Field Name='PercentComplete'>1</Field>"
                    + "<Field Name='_ModerationStatus'>0</Field>"
            //+ "<Field Name='ws_TaskStatus'>Approved</Field>" // This result in an error (column is not defined)
                    + "</Method>";
     
    XmlNode response = listProxy.UpdateListItems(listID, batchElement);
    Console.WriteLine(response.InnerText);

     

    Using Client Object Model:

    cxt.Load(item);
    
    item["Status"] = "Completed";
    item["Completed"] = true;
    item["PercentComplete"] = 1;
    item["WorkflowOutcome"] = "Approved";
    item["FormData"] = "Approved";
    item["_ModerationStatus"] = "0";
    item.Update();
    
    cxt.ExecuteQuery();
    

     

    The result for both methods is that the task list item is updated but the workflow doesn't move forward.

    I have read some workarounds, below, but none of them are working:
    1- WorkflowOutput is  readonly and you have to update FormData instead
    2- Using Moderate in web services instead of update
    3- Update a field called ows_TaskStatus or ws_TaskStatus.

    I have noticed that there is a difference between the ExtendedProperties of an item that has been approved manually and the one that was updated programatically. For the item that has been approved manually the extended properties show, among other items, ws_TaskStatus='Approved' however in the items used programatically this property is missed.

    Can someone show me how to approve a task item programatically using any method?

    Best regards,
    Shehab.

    Wednesday, February 02, 2011 10:26 AM

Answers

  • After a lot of trials and investigation I just had the following code working to approve the task

    SPSite site = new SPSite("http://servername/");
    using (SPWeb web = site.OpenWeb())
    {
      SPList list = web.Lists["TestList"];
      SPListItem item = list.GetItemById(22);
      SPWorkflow workflow = item.Workflows[0];
      SPWorkflowTask task = workflow.Tasks[0];
    
      Hashtable ht = new Hashtable();       
      ht[SPBuiltInFieldId.Completed] = "TRUE";
      ht["Completed"] = "TRUE";
      ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
      ht["PercentComplete"] = 1.0f;
      ht["Status"] = "Completed";
      ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
      ht[SPBuiltInFieldId.WorkflowOutcome] = "Approved";
      ht["TaskStatus"] = "Approved";
      ht["FormData"] = SPWorkflowStatus.Completed;
    
      web.AllowUnsafeUpdates = true;
      SPWorkflowTask.AlterTask((task as SPListItem), ht, true);
    }
    

    I suspect that ht["TaskStatus"] = "Approved"; is that attribute that solved it. Anyway I will try to narrow on the set of properties that need to be changed.

    • Marked as answer by Shehab Kamal Wednesday, February 23, 2011 10:32 AM
    Wednesday, February 23, 2011 10:32 AM

All replies

  • HI Shehab,

     

    Thanks for your post.

    Instead of using the Lists.asmx, have you tried to use the workflow.asmx to do this?

    There is a Workflow.AlterToDo method, in this web service.

    Updates the task information for a specific workflow task.

     

    Here is a demo about this:

    http://msdn.microsoft.com/en-us/library/cc296356.aspx

     

    More information:

    http://msdn.microsoft.com/en-us/library/workflow.workflow.altertodo(v=office.12).aspx

    http://social.msdn.microsoft.com/Forums/en/sharepointworkflow/thread/68bef3d6-572e-419a-a710-789d37756d15

    Friday, February 04, 2011 7:05 AM
  • Hi Wayne, Thanks for the reply, I have followed the demo but still cannot approve the task / todo item.
    I have tried the following code:

    int todoID = 118;
    Guid tasklistID = new Guid("{79ABFDE7-0398-4AD7-918A-0D40204E7726}");
    string itemURL = "http://vphq-sp2010dev/TestLibrary/volshext.log";
    XmlDocument taskData = new XmlDocument();
    taskData.Load(@"..\..\TaskData.xml");
    
    try
    {
      XmlNode response = listProxy.AlterToDo(itemURL, todoID, tasklistID, taskData.DocumentElement); // Returns <fSuccess> tag with the value of 1
      Console.WriteLine(response.InnerText);
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.Message);
    }
    
    The XML I am using is
    <myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD" >
      <TaskStatus>#</my:TaskStatus>
      <Comments />
      <DelegateTo />
      <NewDescription>Please approve Workflow Demo</my:NewDescription>
      <NewDueDate />
      <RequestTo />
      <Decline>0</my:Decline>
      <dcr>0</my:dcr>
      <Status>Completed</my:Status>
    </my:myFields>
    

    The todo item gets updated and the status changes to completed but the workflow outcome is empty and the workflow doesn't move to the next step.

    Any ideas.

     

    Wednesday, February 09, 2011 7:09 AM
  • I have made another trial using SharePoint server object model but I end up updating the task but not approving the workflow.
    Here is my code:

    
    SPSite site = new SPSite("http://sitenamehere/");
    using (SPWeb web = site.OpenWeb())
    {
    	SPList list = web.Lists["Shared Documents"];
    	//SPListItem item = list.GetItemById(18);
    	SPListItem item = list.GetItemByUniqueId(new Guid("5300d16e-94f8-4338-8206-4a57ab7c369b"));
    	SPWorkflow workflow = item.Workflows[0];
    	SPWorkflowTask task = workflow.Tasks[0];
    
    	Hashtable ht = new Hashtable();				
    	ht[SPBuiltInFieldId.Completed] = "TRUE";
    	ht["Completed"] = "TRUE";
    	ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
    	ht["PercentComplete"] = 1.0f;
    	ht["Status"] = "Completed";
    	ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
    	//ht["TaskStatus"] = "#";
    	//ht["ows_TaskStatus"] = "Approved";
    	//ht["FormData"] = SPWorkflowStatus.Completed;
    	//ht["Outcome"] = "Approved";
    	//task.ModerationInformation.Status = SPModerationStatusType.Approved;
    
    	web.AllowUnsafeUpdates = true;
    	SPWorkflowTask.AlterTask((task as SPListItem), ht, true);
    }
    
    Can you tell how to approve a workflow task. I have tried so many alternatives but all of them are not working.
    Monday, February 21, 2011 12:55 PM
  • After a lot of trials and investigation I just had the following code working to approve the task

    SPSite site = new SPSite("http://servername/");
    using (SPWeb web = site.OpenWeb())
    {
      SPList list = web.Lists["TestList"];
      SPListItem item = list.GetItemById(22);
      SPWorkflow workflow = item.Workflows[0];
      SPWorkflowTask task = workflow.Tasks[0];
    
      Hashtable ht = new Hashtable();       
      ht[SPBuiltInFieldId.Completed] = "TRUE";
      ht["Completed"] = "TRUE";
      ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
      ht["PercentComplete"] = 1.0f;
      ht["Status"] = "Completed";
      ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
      ht[SPBuiltInFieldId.WorkflowOutcome] = "Approved";
      ht["TaskStatus"] = "Approved";
      ht["FormData"] = SPWorkflowStatus.Completed;
    
      web.AllowUnsafeUpdates = true;
      SPWorkflowTask.AlterTask((task as SPListItem), ht, true);
    }
    

    I suspect that ht["TaskStatus"] = "Approved"; is that attribute that solved it. Anyway I will try to narrow on the set of properties that need to be changed.

    • Marked as answer by Shehab Kamal Wednesday, February 23, 2011 10:32 AM
    Wednesday, February 23, 2011 10:32 AM
  • Hi

    I am getting error while approving an approval workflow's task in infopath 2010 code. Given below is the log messages.

    08/29/2013 09:12:27.01 	w3wp.exe (0x109C)                       	0x16E0	SharePoint Foundation         	Logging Correlation Data      	xmnv	Medium  	Name=Request (POST:http://sp2010dev:80/Accounting/_layouts/Postback.FormServer.aspx)	4308b075-16da-4019-ae93-5c99ec0a8ff3
    08/29/2013 09:12:27.08 	w3wp.exe (0x109C)                       	0x16E0	SharePoint Foundation         	Logging Correlation Data      	xmnv	Medium  	Site=/	4308b075-16da-4019-ae93-5c99ec0a8ff3
    08/29/2013 09:12:27.09 	w3wp.exe (0x109C)                       	0x16E0	SharePoint Foundation         	Web Controls                  	cm8z	Medium  	Failed to get SPGroupName from GroupID. Error Message: Group cannot be found.  Callstack:    at Microsoft.SharePoint.SPGroupCollection.GetByID(Int32 id)     at Microsoft.SharePoint.WebControls.PeopleEditor.set_SharePointGroupID(Int32 value).	4308b075-16da-4019-ae93-5c99ec0a8ff3
    08/29/2013 09:12:27.16 	w3wp.exe (0x109C)                       	0x16E0	InfoPath Forms Services       	Runtime - Business Logic      	82g6	Warning 	Business logic failed due to an exception. (User: HG\extranet1, Form Name: BusinessExpenseFormNewVersion, IP: , Request: http://sp2010dev/Accounting/_layouts/FormServer.aspx?XmlLocation=/Accounting/BusinessExpenseForm/ExpenseForm_2013-08-29T08_40_48.xml&Source=http://sp2010dev/accounting/BusinessExpenseForm/Forms/AllItems.aspx&DefaultItemOpen=1, Form ID: urn:schemas-microsoft-com:office:infopath:BusinessExpenseFormNewVersion:-myXSD-2013-03-15T08-30-13, Type: FormatException, Exception Message: Input string was not in a correct format.)	4308b075-16da-4019-ae93-5c99ec0a8ff3
    08/29/2013 09:12:27.16 	w3wp.exe (0x109C)                       	0x16E0	InfoPath Forms Services       	Runtime - Business Logic      	7tge	Medium  	Exception thrown from business logic event listener: System.FormatException: Input string was not in a correct format.     at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)     at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)     at System.Convert.ToInt32(String value)     at BusinessExpenseForm.FormCode.btnReject_Clicked(Object sender, ClickedEventArgs e)     at Microsoft.Office.InfoPath.Server.SolutionLifetime.ButtonEventHost.<>c__DisplayClass6.<>c__DisplayClassa.<add_Clicked>b__3()     at Microsoft.Office.InfoPath.Server.Util.DocumentReliability.InvokeBusinessLogic(Thunk thunk)     at Microsoft.Office.InfoPath.Server.SolutionLifetime.ButtonEventHost.FireClickedEvent(Documen...	4308b075-16da-4019-ae93-5c99ec0a8ff3
    08/29/2013 09:12:27.16*	w3wp.exe (0x109C)                       	0x16E0	InfoPath Forms Services       	Runtime - Business Logic      	7tge	Medium  	...t document, ClickedEventArgs args)     at Microsoft.Office.InfoPath.Server.DocumentLifetime.OMExceptionManager.CallFormCodeWithExceptionHandling(UserMessages userMessages, OMCall d)	4308b075-16da-4019-ae93-5c99ec0a8ff3
    08/29/2013 09:12:27.16 	w3wp.exe (0x109C)                       	0x16E0	InfoPath Forms Services       	Runtime                       	961x	Medium  	Not persisting state for request due to previous errors. Form Template: urn:schemas-microsoft-com:office:infopath:BusinessExpenseFormNewVersion:-myXSD-2013-03-15T08-30-13	4308b075-16da-4019-ae93-5c99ec0a8ff3
    08/29/2013 09:12:27.20 	w3wp.exe (0x109C)                       	0x16E0	SharePoint Server             	State Service                 	8kfs	Medium  	The StateManager is disposing and calling ReleaseLockedStates() (Count=0)	4308b075-16da-4019-ae93-5c99ec0a8ff3
    08/29/2013 09:12:27.20 	w3wp.exe (0x109C)                       	0x16E0	SharePoint Foundation         	Monitoring                    	b4ly	Medium  	Leaving Monitored Scope (Request (POST:http://sp2010dev:80/Accounting/_layouts/Postback.FormServer.aspx)). Execution Time=189.999	4308b075-16da-4019-ae93-5c99ec0a8ff3



    The code is working fine on other sharepoint server site.

    here is my code.

    public void btnApprove_Clicked(object sender, ClickedEventArgs e)
            {
                string CurrentWebUrl = SPContext.Current.Web.Url;
                using (SPSite site = new SPSite(CurrentWebUrl))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        web.AllowUnsafeUpdates = true;
                        int id = Convert.ToInt32(MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:RequestNo", NamespaceManager).Value);
                        SPList Mainlist = web.Lists["BusinessExpenseForm"];
                        SPListItem item = Mainlist.GetItemById(id);
                        SPWorkflow workflow = item.Workflows[0];
    
                        string CurrentStatus = MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:RequestStatus", NamespaceManager).Value;
    
                        if (CurrentStatus == "Submitted")
                        {
                            foreach (SPWorkflowTask task in workflow.Tasks)
                            {
                                SPFieldUserValue uservaue = new SPFieldUserValue(web, task["AssignedTo"].ToString());
                                if (SPContext.Current.Web.CurrentUser.Name == uservaue.LookupValue)
                                {
                                    Hashtable ht = new Hashtable();
                                    ht[SPBuiltInFieldId.Completed] = "TRUE";
                                    ht["Completed"] = "TRUE";
                                    ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
                                    ht["PercentComplete"] = 1.0f;
                                    ht["Status"] = "Completed";
                                    ht["ows_FieldName_Comments"] = MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:ManagerCommentsSec/my:ManagerComments", NamespaceManager).Value;
                                    ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
                                    ht[SPBuiltInFieldId.WorkflowOutcome] = "Approved";
                                    ht["TaskStatus"] = "Approved";
                                    ht["FormData"] = SPWorkflowStatus.Completed;
                                    SPWorkflowTask.AlterTask((task as SPListItem), ht, true);
                                }
    
                            }
    
                            web.AllowUnsafeUpdates = false;
                        }
                    }
    
                }
            }


    Dont know what is going wrong in working on one server and failing on other server. expecting solution from this thread. 

    thank you beforehand. 


    Thanks & Regards Raj


    • Edited by RajKumarBathula Thursday, August 29, 2013 5:00 PM added some more info
    Thursday, August 29, 2013 4:19 PM