Deploy Nintex Workflow from wsp

16/10/2015 10:59

Nintex workflows are great product to cooperate with SharePoint, but it's designed to move it between environments by export/import manually.

Fortunately it's a way how to include Nintex workflows in Sharepoint solution package, so that they are deployed together with solution and working mostly without additional manual steps.


Here is a brief concept how to do it:

1. Export your workflows from develpment environment, so that you get .nwf files. The prerequisity for this point is to make your workflow as much environment independent as possible, follow practices described in Moving Nintex workflow between environments. If there are still some developer values left, replace them manualy in nwf file in Visual Studio by token - some text which should be unique in the file, and this value replace later in feature receiver when publishing workflow.

2. Add .nwf files to solution in Visual Studio, to Layouts mapped folder


3. Combine your developer site url with nintex web service url (e. g. https://myserver/sites/devsite/_vti_bin/nintexworkflow/workflow.asmx)

4. Add web service reference from address above to Visual Studio and name it e. g. NintexWS

5. Add site scoped feature with event receiver with content as in example bellow:

   Feature activates needed Nintex feature on the site (also web scoped), reads nwf files from layouts folder and calls nintex web service to publish these files (sometimes after some modification) to dedicated lists on the sharepoint site.

5.1 Replace following data, your workflow file names, instance names, list names where to publish workflow, your subfolder path in layouts folder

5. 2 In case you have some environment dependencies included in .nwf files, you can replace them with current values before publishing.


using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using System.Text;
using Microsoft.SharePoint.Utilities;
using System.IO;

namespace Your_namespace
{
  
    [Guid("fa0be4a2-b3b5-4064-a267-b010055ef9fc")]
    public class YourProjectClassEventReceiver : SPFeatureReceiver
    {
        private string webUrl;

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {

            SPSite site = properties.Feature.Parent as SPSite;
            SPWeb web = site.RootWeb;
            //Activate NINTEX features
            //Site features
            FeatureHelper.ActivateFeature(site, new Guid("0561d315-d5db-4736-929e-26da142812c5"), 15); //Nintex Workflows 2013
            FeatureHelper.ActivateFeature(site, new Guid("eb657559-be37-4b91-a369-1c201183c779"), 15); //Nintex WPs
            //Web features
            FeatureHelper.ActivateFeature(web, new Guid("9bf7bf98-5660-498a-9399-bc656a61ed5d"), 15); //Nintex Workflows 2013

            webUrl = web.Url;

            string webServiceUrl = SPUrlUtility.CombineUrl(webUrl, "_vti_bin/nintexworkflow/workflow.asmx");

            SPSecurity.RunWithElevatedPrivileges(delegate() //elevated are needed for activating feature by user - from UI
            {
                //Call the Nintex web service to publish/save the workflows
                NintexWS.NintexWorkflowWS service = new NintexWS.NintexWorkflowWS();
                service.Url = webServiceUrl;
                service.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

                PublishWorkflowFile(service, "Schvalenie_Expense_reportu.nwf", "Schvalenie Expense reportu", "Expense Report");
                PublishWorkflowFile(service, "Schvalovanie_Cestovneho_prikazu.nwf", "Schvalovanie Cestovneho prikazu", "Request");
            });
        }

        private void PublishWorkflowFile(NintexWS.NintexWorkflowWS service, string workflowFileName, string workflowInstanceName, string listName)
        {
            try
            {
                byte[] workflowFile = GetWorkflowNWF(workflowFileName);
                bool retVal = service.PublishFromNWF(workflowFile, listName, workflowInstanceName, true);
                if (!retVal)
                {
     //here you can use your logging
                    //Logging.LogInformation(string.Format("Error occured during publishing nintex workflow '{0}' to '{1}' on '{2}'", workflowFileName, listName, webUrl));
                }
            }
            catch (Exception ex)
            {
    //here you can use your logging
                Logging.LogError(ex);
                throw;
            }
        }

        private byte[] GetWorkflowNWF(string workflowFileName)
        {
            string txt = "";

            string templateFilePath = SPUtility.GetCurrentGenericSetupPath(@"Template\Layouts\CP\NintexWF\");
            templateFilePath = System.IO.Path.Combine(templateFilePath, workflowFileName);

            //Replace fake id with real id
            using (FileStream nwfFile = new FileStream(templateFilePath, FileMode.Open, FileAccess.Read))
            {
                using (StreamReader reader = new StreamReader(nwfFile))
                {

                    txt = reader.ReadToEnd();
                    //todo: here you can replace any tokens if you use some
                  
                }
            }
            return Encoding.UTF8.GetBytes(txt);

        }
     
    }
}