So I had a reusable SharePoint Designer list workflow deployed in SharePoint 2013. The process that I’m implementing is creating project sites using web templates created in Visual Studio 2013.

When a list item is created my web template created a document library and also activates a feature to enable my reusable workflow.

First I created a features and added the activation code:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
                SPWeb web = (SPWeb)properties.Feature.Parent;
                AssociateWorkflowsToLists(web.Url, “Documents”, “Add Secure Comment”, “Add Comment Securely”, “Workflow Tasks”, “Workflow History”);
            }
            catch (Exception Ex)
            {
            }
        }

Then I implemented the associateWorkflowsToLists method. There were a couple of challenges that I faced on the way.

  • The history list doesn’t get created within the local web
  • Not the right permissions do create the workflow.
  • The workflow doesn’t work after it is created

History list creation

First try to access the list and then within the Catch I’m creating the history list.

try

{

         SPList histList = web.Lists[historyList];

}

catch (ArgumentException aEx)

{

      // create history list when it doesn’t exist.

    Guid listGuid = web.Lists.Add(historyList, “Workflow History List”, SPListTemplateType.WorkflowHistory);

     SPList histList = web.Lists[listGuid];

     histList.Hidden = true;

     histList.Update();

 }

Permissions

To get my permissions sorted I elevated permissions

SPSecurity.RunWithElevatedPrivileges(delegate()                

{

                    using (SPSite site = new SPSite(webUrl))                    

                   {                        

                               using (SPWeb web = site.OpenWeb())                        

                               {

// My code goes here

                               }

                  }

              });

The finally the most complicated bit. actually it’s not complicated but there is very little documentation to find. The reusable workflow that is deployed needs to be republished. So I guessed that all I needed to do was publish the reusable workflow ( this worked in SharePoint designer so why wouldn’t it work in code). Before you do a publish in the code you first have to save the workflow. Most likely this is what SharePoint designer does internally.

// Re-Publish the Definition. First a refresh Load, then a save  followed by publish                                   

                                    workflowDeploymentService.RefreshLoad();

                                    clientContext.ExecuteQuery();

                                    workflowDeploymentService.SaveDefinition(unpublishedWorkflowDefinition);

                                    clientContext.ExecuteQuery();

                                    workflowDeploymentService.PublishDefinition(unpublishedWorkflowDefinition.Id);

                                    clientContext.ExecuteQuery();    

For the complete code see below:

protected void AssociateWorkflowsToLists(string webUrl, string listname, string workflowName, string associationName, string taskList, string historyList)        

            try

{                

                HttpContext.Current = null;                

                SPUtility.ValidateFormDigest();

                Guid listId = new Guid();                

               Guid workflowTaskListId = new Guid();                

               Guid workflowHistoryListId = new Guid();

               SPSecurity.RunWithElevatedPrivileges(delegate()   

               {

                    using (SPSite site = new SPSite(webUrl))                    

                   {                        

                               using (SPWeb web = site.OpenWeb())                        

                               {

                                     try

                                   {

                                        SPList histList = web.Lists[historyList];

                                    }

                                    catch (ArgumentException aEx)

                                    {

                                                // create history list when it doesn’t exist.

                                              Guid listGuid = web.Lists.Add(historyList, “Workflow History List”, SPListTemplateType.WorkflowHistory);

                                         SPList histList = web.Lists[listGuid];

                                              histList.Hidden = true;

                                              histList.Update();

                                    }

                                   workflowHistoryListId = web.Lists[historyList].ID;                            

                                   workflowTaskListId = web.Lists[taskList].ID;

                                   listId = web.Lists[listname].ID;

                                   var clientContext = new ClientContext(web.Url);

                                   var workflowServiceManager = new WorkflowServicesManager(clientContext, clientContext.Web);

                                   var workflowDeploymentService = workflowServiceManager.GetWorkflowDeploymentService();

var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService();

                      // Having a look which workflows are already there on the site (finding the reusable workflow)

                            // Publish the workflow to the list                            

                           var unpublishedWorkflowDefinitions = workflowDeploymentService.EnumerateDefinitions(false);                            

                           clientContext.Load(unpublishedWorkflowDefinitions);

                            clientContext.ExecuteQuery();

                            foreach (var unpublishedWorkflowDefinition in unpublishedWorkflowDefinitions)

                            {     

                                      Console.WriteLine(“{0} – {1}”, unpublishedWorkflowDefinition.Id, unpublishedWorkflowDefinition.DisplayName);

                                            if (unpublishedWorkflowDefinition.DisplayName == workflowName)

                                            {

                                             // Re-Publish the Definition. First a refresh Load, then a save  followed by publish                                   

                                    workflowDeploymentService.RefreshLoad();

                                    clientContext.ExecuteQuery();

                                    workflowDeploymentService.SaveDefinition(unpublishedWorkflowDefinition);

                                    clientContext.ExecuteQuery();

                                    workflowDeploymentService.PublishDefinition(unpublishedWorkflowDefinition.Id);

                                    clientContext.ExecuteQuery();                                                                                                 

// Create new subscription

                                    WorkflowSubscription newSubscription = new WorkflowSubscription(clientContext)

                                    {

                                        DefinitionId = unpublishedWorkflowDefinition.Id,

                                        Enabled = true,

                                         Name = associationName

                                    };

                                    var startupOptions = new List<string>();

                                    startupOptions.Add(“WorkflowStart”);

                                    newSubscription.EventTypes = startupOptions;

                                    newSubscription.SetProperty(“HistoryListId”, workflowHistoryListId.ToString());

                                    newSubscription.SetProperty(“TaskListId”, workflowTaskListId.ToString());

                                    var result = workflowSubscriptionService.PublishSubscriptionForList(newSubscription, listId);

                                     clientContext.ExecuteQuery();                                    

                                }

                            }

                        }

                    }

                });

            }

            catch (Exception Ex)            

            {             }

        }

 

Avatar for Pieter Veenstra

By Pieter Veenstra

Business Applications Microsoft MVP working as the Head of Power Platform at Vantage 365. You can contact me using contact@sharepains.com

4 thoughts on “SharePoint 2013 – Workflow Manager 1.0 – How to publish a list workflow programmatically”
  1. Imran Kahn:

    I am working on Delegation in PWA settings in Project Server 2013.
    In my scenerio, I have two users, one is Umair and other is Salman. Both users have administrative rights and we are performing the ACT AS A DELEGATE for Salman. Umair will be working on the behave of Salman. Once we started the Start Delegate Session, a workflow created a Task for Salman which should be sent task notification email to Umair because Umair is working on the behalf of Salman but not task history is created for EPT type and also,neither Salman nor Umair didn’t receive email for task notification. I am waiting for your earliest reply.Thank you.

  2. Hi Imran,

    SharePoint workflows and Project Server workflows are not the same.

    Have a look at this article:

    http://office.microsoft.com/en-gb/project-server-help/alert-or-remind-me-of-changes-with-e-mail-notifications-HA01164389.aspx?CTT=5&origin=HA010250975

    By default only the following events generate alerts:

    Rejected Assignments (by Resource)
    Rejected Task Updates (by Manager)
    Rejected New Tasks (by Manager)
    Rejected Calendar Updates (by Manager)
    Rejected Task Delegation Requests (by Manager)
    Removed from a Status Report (by Manager)

  3. Thank you very much for this article. But after republish, the old workflow is still not function. The new workflow association works fine. How do I delete the old workflow?

Leave a Reply to Pieter VeenstraCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from SharePains by Microsoft MVP Pieter Veenstra

Subscribe now to keep reading and get access to the full archive.

Continue reading