Designing and deployment of Context Data in Nintex Workflow

Context Data in Nintex Workflow represent values specific to the workflow, the context of the item and the current task within the workflow. As an example below are some of them

Initiator: The username (domain\username) who caused the item to be entered into the workflow

Item URL: The URL of the item in workflow

The complete list of Contex Data items and how to manage it is described  in Nintex Workflow User Manual.

Designing custom Context Data usually include the implementation of specific handler(class). In Nintex Workflow API  for this purposes exist class ContextDataItemBase, from which all Context Data items usually inherits.

The implementation of Context Data for returning approvers comments in XML format is presented below

/// <summary>
/// Context DataItem for All Approvers in Xml format
/// </summary>
public class AllApproverCommentsXml : ContextDataItemBase
{
/// <summary>
///
/// </summary>
/// <param name="ctx"></param>
/// <returns></returns>
public override object GetValueObject(NWWorkflowContext ctx)
{
return GetLastApproverCommentsAsXml(ctx);
}
internal string GetLastApproverCommentsAsXml(NWWorkflowContext ctx)
{
return new NintexTaskCollection(ctx.InstanceID, ctx.Web).GetAllApprovalTaskCommentsAsXml();
}
/// <summary>
/// Internal Name
/// </summary>
public override string InternalName
{
get { return "AllApproverCommentsXml"; }
}
}

Below is shown page for managing Context Data with custom Context Data added  and Insert Reference dialog that demonstrates the usage of custom Context Data when designing workflow   

Now our goal to automate the deployment of Context Data. For example, it is possible to create Data Context item during feature activation. For this task we’ll use method of class CustomCommonDataCollection (in namespace:Nintex.Workflow) from Nintex Workflow API:

public static void Add(string typeName, string assemblyName, string displayName, string description)

Adding Context Data item  in Nintex Workflow Management (shown below)

is equivalent to calling

CustomCommonDataCollection.Add(
"SharePoint.NW2010.Deployment.ContextDataItems.AllApproverCommentsXml",
"SharePoint.NW2010.Deployment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b6acd7f49f7aeb64",
"Approver Comments (XML)",
"Approver comments in XML format");

You could grab the source code for the project that demonstrates how to provision Context Data here.

Automating deployment of reusable workflows in Nintex Workflow 2010

One of the options for creating workflows in Nintex Workflow 2010 (NW2010 for short) is to associate workflows  with Content Types.This category of workflows is known as Reusable workflows.

As stated in Nintex Workflow 2010 User Manual

A resusable workflow template allows the workflow to be used on a content type, list or library through the
default SharePoint Workflow settings option.
Reusable workflow templates can be created for use within a single site or an entire site collection

In our case we are only interested in reusable workflows for content types.

Let’s disscuss the scenario when we need to automate the deployment of reusable workflow. It may take place for example, when there are several environments. The approach discussed here allows to deploy workflows during feature activation.

NW2010 API contains publishing infrastucture (Nintex.Workflow.Publishing namespace) that allow to programatically publish workflow templates.
Class Publish contains  method

WorkflowMetaData PublishAWorkflow(string wfName, NWActionConfigurations configs, Guid listId, SPWeb web, ImportContext importCtx, bool validate, SPContentTypeId contentTypeId, string changeNotes)

view raw
PublishAWorkflow.cs
hosted with ❤ by GitHub

that allows to associate workflow using ContentTypeId parameter.

The method below demonstrate how to deploy reusable workflow file by passing it file name, contenttype name and workflow name(NWFMappingEntry parameter)  using Nintex API PublishAWorkflow method.

/// <summary>
/// Publish Reusable Workflow
/// </summary>
/// <param name="mapping"></param>
public void PublishReusableWorkflow(NWFMappingEntry mapping)
{
SPContentType ct = web.ContentTypes[mapping.BindingName];
string workflowName = mapping.WorkflowName;
string pathToNWF = Path.Combine(properties.Definition.RootDirectory, mapping.WorkflowFileName);
byte[] workflowData = File.ReadAllBytes(pathToNWF);
string workflowFile = Utility.ConvertByteArrayToString(workflowData);
while ((int)workflowFile[0] != (int)char.ConvertFromUtf32(60)[0])
workflowFile = workflowFile.Remove(0, 1);
ExportedWorkflowWithListMetdata workflowWithListMetdata = ExportedWorkflowWithListMetdata.Deserialize(workflowFile);
string xmlMessage = workflowWithListMetdata.ExportedWorkflowSeralized;
SPListCollection lists = web.Lists;
Dictionary<string, Guid> dictionary = new Dictionary<string, Guid>(lists.Count);
foreach (SPList spList in lists)
{
if (!dictionary.ContainsKey(spList.Title.ToUpper()))
dictionary.Add(spList.Title.ToUpper(), spList.ID);
}
foreach (var listReference in workflowWithListMetdata.ListReferences)
{
string key = listReference.ListName.ToUpper();
if (dictionary.ContainsKey(key) && !dictionary.ContainsValue(listReference.ListId))
xmlMessage = xmlMessage.Replace(Utility.FormatGuid(listReference.ListId), Utility.FormatGuid(dictionary[key]));
}
var exportedWorkflow = WorkflowPart.Deserialize<ExportedWorkflow>(xmlMessage);
foreach (var config in exportedWorkflow.Configurations.ActionConfigs)
WorkflowRenderer.ProcessActionConfig(config);
Guid listId = Guid.Empty;
bool validateWorkflow = true;
Publish publish = new Publish(web);
publish.PublishAWorkflow(workflowName, exportedWorkflow.Configurations, listId, web, (ImportContext)null, validateWorkflow, ct.Id, string.Empty);
}

Project that demonstrates how to deploy Nintex reusable workflows may be found here