So I had a reusable SharePoint Designer 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)            

            {             }

        }

 

Advertisements