Provision a Workflow to the Host Web from the App Web

Below is some sample code to provision a workflow on the host web from your app web. This sample code is in one block for demo purposes. It makes 4 asynchronous calls to SharePoint to complete successfully.

In the event you’d want to define in your App a workflow that would run on a list in the host web this is the code you would use to deploy (move it from App to Host) and attach it to a list in the host web.

NOTE: you must include a reference to “/_layouts/15/SP.WorkflowServices.js”

   var attachWorkflow = function(workflowName, workflowListName, workflowHistoryListName, workflowTasksListName) {

        //Using the App Web as the client context
		clientContext = new SP.ClientContext.get_current();
   
		//Get the host web URL from the query string params
		//I have a function getHostWebUrl() - which is not included.
		//http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
		var hostWebUrl = getHostWebUrl();
		
		//Using the hostWebContext as an AppContextSite
        hostWebContext = new SP.AppContextSite(clientContext, hostWebUrl);
        
		//Get the Workflow Services Manager for the Host web, NOTE: you initialize it with the clientContext & the hostWebContext Web)
        var hostWebWorkflowServicesManager = new SP.WorkflowServices.WorkflowServicesManager.newObject(clientContext, hostWebContext.get_web());
        var hostWebWorkflowDeploymentService = hostWebWorkflowServicesManager.getWorkflowDeploymentService();
        var hostWebSubscriptionService = hostWebWorkflowServicesManager.getWorkflowSubscriptionService();

		//Get the Workflow Services Manager for the App web 
        var workflowServicesManager = new SP.WorkflowServices.WorkflowServicesManager(clientContext, clientContext.get_web());
        var workflowDeploymentService = workflowServicesManager.getWorkflowDeploymentService();
        var workflowDeploymentServiceDefinitions = workflowDeploymentService.enumerateDefinitions(false);

		//Load all the Workflow Definitions from the App web
        clientContext.load(workflowDeploymentServiceDefinitions);
        clientContext.executeQueryAsync(function () {

			//Get the enumerator for all the workflow definitions in the App web
            var workflowDefinitions = workflowDeploymentServiceDefinitions.getEnumerator();
            while (workflowDefinitions.moveNext()) {

				//set the current definition to a variable
                var workflowDefinition = workflowDefinitions.get_current();
				//test, trying to locate your workflow in the App web
                if (workflowDefinition.get_displayName() === workflowName) {

					//now grab the xaml definition of the selected workflow
                    var workflowXaml = workflowDefinition.get_xaml();

					//define a new workflow and assign it xaml & name
                    var newWorkflow = new SP.WorkflowServices.WorkflowDefinition.newObject(clientContext, hostWebContext.get_web());
                    newWorkflow.set_xaml(workflowXaml);
                    newWorkflow.set_displayName(workflowName);
					
					//using the host webs Workflow Deployment Service, save the workflow.
                    hostWebWorkflowDeploymentService.saveDefinition(newWorkflow);
                    
					//load the new workflow and initialize the Id
					clientContext.load(newWorkflow, "Id");
					//this query will save your workflow to the host web
                    clientContext.executeQueryAsync(function() {

						//publish the workflow on the host web
                        hostWebWorkflowDeploymentService.publishDefinition(newWorkflow.get_id());
						
						//getting all the lists that the workflow will attach to
						//these lists already created on the host web
                        var targetList = hostWebContext.get_web().get_lists().getByTitle(workflowListName);
                        var historyList = hostWebContext.get_web().get_lists().getByTitle(workflowHistoryListName);
                        var tasksList = hostWebContext.get_web().get_lists().getByTitle(workflowTasksListName);

						//loading the lists & initialize the Id
                        clientContext.load(targetList, "Id");
                        clientContext.load(historyList, "Id");
                        clientContext.load(tasksList, "Id");

						//this query will publish the workflow and get the required list id's for the next step
                        clientContext.executeQueryAsync(function() {

								//creating a new workflow subscription
                                var subscription = new SP.WorkflowServices.WorkflowSubscription(clientContext, hostWebContext.get_web());

								//setting some properties of the subscription
                                subscription.set_name(workflowName + "-ItemAdded");
                                subscription.set_enabled(true);
                                subscription.set_definitionId(newWorkflow.get_id().toString());
                                subscription.set_eventSourceId(targetList.get_id());
                                subscription.set_eventTypes(["ItemAdded"]);

								subscription.setProperty("TaskListId", tasksList.get_id().toString());
                                subscription.setProperty("HistoryListId", historyList.get_id().toString());
                                subscription.setProperty("FormData", "");

								//attaching the subscription to the target list 
                                hostWebSubscriptionService.publishSubscriptionForList(subscription, targetList.get_id());

								//this query will execute the creation of the new subscription and adding attaching the subscription to the target list on the host web
                                clientContext.executeQueryAsync(function() {
                                    console.log("Workflow : \"" + workflowName + "\" successfully added to list : \"" + workflowListName + "\"");
                                }, function(sender, args) {
                                    console.log("Workflow : " + workflowName + " not successfully added to list : " + workflowListName);
                                    console.log("Reason : " + args.get_message() + "");
                                });
                            },
                            function(sender, args) {
                                console.log("Failed to get workflow list IDs");
                                console.log("Reason : " + args.get_message() + "");
                            });

                    }, function(sender, args) {
                        console.log("Failed to create the workflow definition");
                        console.log("Reason : " + args.get_message() + "");
                    });
                }
            }
        }, function (sender, args) {
            console.log("Could not find workflow : " + workflowName);
            console.log("Reason : " + args.get_message() + "");
        });
    };

8 Comments

  1. Nice Article, Thanks for sharing.
    I want to know is it possible to deploy custom workflow activities from App web to hostweb?

    Thank you

    • Hi cv,

      Did you ever figure this out? It seems that if your workflows contain custom activities, you get an error trying to deploy the workflows from app web to host web. Do you know if there is a way of programmatically deploy the actvities to host web?

      Thanks

  2. I trying your code and it’s creating the workflow and association but not carrying over the initiation form. Is there something that needs to be set on the subscription object or elsewhere to set the workflow to first call the init form?

      • Hi Thomas,
        Can I use above code to associate workflow from app web to host web on ONPREMISES SharePoint 2013. Seems everyone are talking about associating on SharePoint online only. Is there a way to associate a app workflow to already created host web in SharePoint ONPREMISES.

        Thank you

Leave a Reply

Your email address will not be published. Required fields are marked *

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