3

I have configured SharePoint OOTB Approval workflow on a library. In workflow I have added 3 stages of approval and 1st stage of approval is completed so workflow is in 2nd stage of approval.

Now I want to retrieve all users who are in 2nd stage of approval programmatically.

How can I do it? Please suggest.

3
  • can't you just retrieve them from the workflow task list?
    – thomius
    Apr 21, 2014 at 9:57
  • I tried that also. If I have 3 approvers in 2nd stage and no one has completed their task then it is OK but if someone from 2nd stage complete his/her task then how is it possible to get that user? (I have checked feasibility by task created date&time but it is not 100% accurate in my case.) Apr 21, 2014 at 10:25
  • You can take, "Modified By", as Assigned to is the assigned user, and when you approve a task it gets put into Modified By. will give approver
    – Anuja
    Apr 21, 2014 at 11:00

1 Answer 1

1

There is not a real supported way to do this.

Getting the workflow instance is fairly easy as that is in the collection SPListItem.Workflows you may want to add some check that the ParentAssociation has the right name, ...

Getting the original assigned approvers for when the workflow was associated with the list is also easy as that xml is in SPWorkFlow.ParentAssociation.AssociationData

So if we could just trust that the users isn't changing the list of approvers then it's just parsing that XML.

The hard part is that when the users change data at instantiation of the workflow then the only supported way of getting that data in through SPWorkflowActivationProperties.InitiationData inside the workflow.

The OOTB Approval workflow seems to store that data as modifications with the TypeId 64aefd44-fd54-48c1-93c0-86f2f7c71be, so we can hack our way in and find it, but it's not a supported way (i.e. if it fails you'll not be able to get help from MS)

The following programs list stage two approvers for a the doc lib http://sp2010/Test and may need some improvements for handling groups, but should get you started:

using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;

namespace ListApprovers
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var site = new SPSite("http://sp2010"))
            using (var web = site.OpenWeb())
            {
                var list = web.Lists["Test"];
                foreach (SPListItem item in list.Items)
                {
                    Console.WriteLine("Item: {0}", item.File.Name);
                    foreach (SPWorkflow wfi in item.Workflows)
                    {
                        if (wfi.InternalState != SPWorkflowState.Running)
                            continue;

                        // Got a running Workflow instance
                        //
                        var associationDataXML = wfi.ParentAssociation.AssociationData;
                        if (string.IsNullOrEmpty(associationDataXML))
                            continue;

                        // Got at least some AssociationData
                        //
                        XDocument associationData;
                        try
                        {
                            associationData = XDocument.Parse(associationDataXML);
                        }
                        catch (XmlException)
                        {
                            // AssociationData isn't XML
                            continue;
                        }

                        // AssociationData is XML
                        //
                        var nsmgr = new XmlNamespaceManager(new NameTable());
                        nsmgr.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
                        nsmgr.AddNamespace("d", "http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields");
                        nsmgr.AddNamespace("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
                        nsmgr.AddNamespace("my", "http://myDummyNS"); // Added to handle invalid XML in modifications contextdata :-(
                        var stages = associationData.XPathSelectElements("/dfs:myFields/dfs:dataFields/d:SharePointListItem_RW/d:Approvers/d:Assignment", nsmgr).ToArray();
                        if (stages.Length < 2)
                            continue;

                        // Matches Approval Workflow with at least 2 stages
                        //
                        var approvers = stages[1].XPathSelectElements("./d:Assignee/pc:Person/pc:AccountId", nsmgr).Select(e => e.Value).ToArray();

                        // Got original approvers from association
                        //
                        foreach (SPWorkflowModification modification in wfi.Modifications)
                        {
                            if (modification.TypeId == new Guid("64aefd44-fd54-48c1-93c0-86f2f7c71be5"))
                            {
                                // Got Modification for Approvers
                                //
                                var contextData = XDocument.Parse("<my:DummyRoot xmlns:my=\"http://myDummyNS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + modification.ContextData + "</my:DummyRoot>");
                                var modifiedApprovers = contextData.XPathSelectElements("/my:DummyRoot/my:NewAssignments/my:Assignment[2]/my:Assignee//pc:Person/pc:AccountId", nsmgr).Select(e => e.Value).ToArray();
                                if (modifiedApprovers.Length > 0)
                                {
                                    approvers = modifiedApprovers;
                                }
                            }
                        }

                        foreach (var approver in approvers)
                        {
                            Console.WriteLine("  {0}", approver);
                        }

                    }
                }
            }
        }
    }
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.