SharePoint 2013 Workflow - Integrating a Custom Association Form
Overview
In SharePoint 2013, the integration of custom forms like Association form, initiation form etc, is different from the way we do it in SharePoint 2010. In 2010 we can use either a InfoPath or ASPX pages. however in SharePoint 2013, per the know issues article, there are no more InfoPath based workflow forms. For the workflow based on SharePoint Designer 2013 and Windows Azure Workflow, SharePoint Designer creates ASPX forms instead of InfoPath forms that were created by SharePoint 2010 workflows. If you want to customize the form, you can click it from the forms slab in workflow summary page to show a generic ASPX page editor
Visual Studio 2012 also provides a rich set of capabilities to create Association and Initiation forms.
The following are the very important capabilities/features added to SharePoint workflow while creating custom workflows using Visual Studio 2012.
- SharePoint 2013 introduced a rich set of client-side object mode (CSOM) based workflow API that's can be fully leveraged in VS2012
- VS2012 Provides a standard Workflow Association and Initiation form templates (ASP.Net form based) out of the box (When SharePoint 2013 templates are installed)
In this article we will be covering the complete set of steps involved in creating a custom workflow form and associating it to the workflow.
Understanding the need of Association Form:
Association and initialization forms are displayed for users to fill out before any workflow is actually started. You can use these forms to enable users to set parameters and other information for the workflow before it starts. In case if there are no custom properties/parameters needs to be associated with the workflow, the association form is not mandatory.
Preparing workflows to be accessed from association forms
In order to pass a parameter/property from the association form to the workflow, the workflow must implement/use an activity called GetConfigurationValue, which is capable/responsible for retrieving the value passed as an association data.
The activity GetConfigurationValue can be located on Runtime group of workflow activities tool box .
Upon adding the activity to the workflow, associate the activity with a variable declared at the workflow level.
You can create as many parameters as required in the same way with appropriate GetConfigurationValue Activity associated with a valid string variable in the workflow.
Upon completion of this change, we are good to go-ahead and add the association form and make necessary changes.
Adding an Association Form
To add an association form to any workflow perform the following steps.
- Right click the workflow folder and select "Add" - "New Item" from the context menu.
- On Add new Item Dialog, select "Workflow Association Form" on Office/SharePoint group
- This will add a new Association form like the one attached to the workflow with default placeholders (2 text boxes, 1 date control, save and cancel button) and basic Ready to Customize CSOM code that could be a good starting point to build (customize) it with your own logic based on your business requirements.
Changes on workflow Elements.Xml
Upon adding the association form, please ensure if the elements.xml associated with the workflow is updated with the entries highlighted below.
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="https://schemas.microsoft.com/sharepoint/">
<Module Name="Approval" Url="wfsvc/73C27777198F43B4A7C0FE6753ADA4C4">
<File Url="Workflow.xaml" Type="GhostableInLibrary" Path="Approval\Workflow.xaml" Level="Published" DoGUIDFixUp="TRUE">
<Property Name="ContentTypeId" Value="0x01002A2479FF33DD4BC3B1533A012B653717004C4A72D4775DB04F8979AE7A4A568F20" />
<Property Name="ContentType" Value="WorkflowServiceDefinition" />
<Property Name="_ModerationStatus" Value="0" />
<Property Name="FileDirRef" Value="wfsvc/73C27777198F43B4A7C0FE6753ADA4C4" />
<Property Name="FSObjType" Value="0" />
<Property Name="FileLeafRef" Value="workflow.xaml" />
<Property Name="isReusable" Value="true" />
<Property Name="RequiresInitiationForm" Value="false" />
<Property Name="RequiresAssociationForm" Value="true" />
<Property Name="WSGUID" Value="{73C27777-198F-43B4-A7C0-FE6753ADA4C4}" />
<Property Name="WSPublishState" Value="3" />
<Property Name="WSDisplayName" Value="Approval" />
<Property Name="WSDescription" Value="Approval" />
<Property Name="RestrictToType" Value="List" />
<Property Name="DisableAutoStartCreate" Value="false" />
<Property Name="DisableManualStart" Value="false" />
<Property Name="AssociationUrl" Value="wfsvc/73C27777198F43B4A7C0FE6753ADA4C4/Approval/AssociationForm.aspx" />
</File>
<File Path="Approval\AssociationForm.aspx" Url="Approval/AssociationForm.aspx" />
</Module>
<ListInstance FeatureId="{2c63df2b-ceab-42c6-aeff-b3968162d4b1}"
TemplateType="4501"
Title="wfsvc"
Description="This list instance is used by SharePoint to keep track of workflows. Do not modify."
Url="wfsvc"
RootWebOnly="FALSE" />
</Elements>
Customizing an Association Form
By this time we will have a Ready to Customize association from its now time to go and customize the same.
The form will be enabled with the following JavaScript method with some default logic.
// ---------- Save workflow association ----------
function associateWF(state, pauseFunction) {
if (complete != 0)
return complete;
var historyListId = "";
var taskListId = "";
var metadata = new Object();
// Get form input values and set workflow in-argument values
var strInputValue = document.getElementById("strInput").value;
if (strInputValue) {
metadata['strArg'] = strInputValue;
}
var intInputValue = document.getElementById("intInput").value;
if (intInputValue) {
var intValue = parseInt(intInputValue);
if (intValue)
metadata['intArg'] = intValue;
}
we can customize this logic to retrieve the content from the modified form elements and might make it something like the following.
// ---------- Save workflow association ----------
function associateWF(state, pauseFunction) {
if (complete != 0)
return complete;
var historyListId = "";
var taskListId = "";
var metadata = new Object();
// Get form input values and set workflow in-argument values
var html = $("#ctl00_PlaceHolderMain_spApprovers_upLevelDiv");
var approvers = $("#divEntityData", html).attr("key");
if (approvers && approvers.length > 0) {
metadata['Approvers'] = approvers;
}
else {
alert("Approvers field cannot be empty"); return;
}
var intDurationDays = document.getElementById("txtDurationDays").value;
if (intDurationDays) {
var intValue = parseInt(intDurationDays);
if (intValue && intValue > 0) {
metadata['Duration'] = intValue;
}
}
var boolFirstApproval = document.getElementById("chkFirstApproval");
if (boolFirstApproval) {
metadata['EndonFirstApproval'] = boolFirstApproval.checked;
}
In addition, the OOB method integrates the following logic as well.
- Get form input values and set workflow in-argument values
- Sets History list id. If its new history list, creates new history list
- Sets task list id. If its new task list, creates new task list
- Checks, if task list contains the OOTB SharePoint 2013 Workflow Task content type
- Associates the workflow to selected triggering option selected on the previous workflow screen (Manual, Item Added, Item Updated)
- If workflow association exists, then we will update its subscription information. Otherwise, it's a new association, and we will add the new subscription.
- Publish the workflow
Editing an existing workflow - Customizing the association form to populate the association parameters
The Association form will not provide any option of populating the association parameter when editing an existing workflow. however this can be achieved by adding a new function and calling it from the function setHeader() which gets executed upon load. For retrieving the subscription info, will have to create an instance of the workflow manger and call the method getSubscription by passing subscription id as an input parameter. The subscription id would be available pre set upon the page load, there is no need to retrieve the subscription id manually.
Upon completion your association form is ready to go and get deployed.
Samples
Sample of a customized association form can be found here.
Sample Approval workflow with a customized association form can be downloaded from here.
Comments
Anonymous
April 23, 2014
Hi Srinivasan, i created a workflow based on your article and published. Worklow opens the association form only for the site owner. When i try to create the workflow with user with Contribute permissions on th e list i get access denied page. Do we have set permissions for the wfsvc list? i managed to go to the permission page of wfsvc list and assign the test user with full control rights then i was able to see association form. But why is that we need to have full rights for this list? did you face this issue? please helpAnonymous
May 21, 2014
I created a workflow with association form.When i tried to add a workflow to the existing list gives [NullReferenceException: Object reference not set to an instance of an object.] Microsoft.SharePoint.Utilities.SPChunkedStringBuffer.Append(String str) +0 Microsoft.SharePoint.WorkflowServices.ApplicationPages.WorkflowAssociationFormContextControl.OnLoad(EventArgs e) +1549 System.Web.UI.Control.LoadRecursive() +70 System.Web.UI.Control.LoadRecursive() +189 System.Web.UI.Control.LoadRecursive() +189 System.Web.UI.Control.LoadRecursive() +189 System.Web.UI.Control.LoadRecursive() +189 System.Web.UI.Control.LoadRecursive() +189 System.Web.UI.Control.LoadRecursive() +189 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3177 the above exceptionAnonymous
May 22, 2014
MSPRGMR: I don't think contribute permission is sufficient for workflow associations. hence use site admin or owner kind of accounts for associations. generally I wont recommend enabling permissions on wfsvc list.Anonymous
May 22, 2014
sk2014: Even I faced this issue on one of my environment, Try upgrading to SP2013 SP1.Anonymous
May 22, 2014
The comment has been removedAnonymous
June 01, 2014
I upgraded to sp1.It is working now. Thank you.