Nintex Workflow - Modifying your Farm UDA

 

The Problem

I love Nintex UDA - it lets me push commonly used logic into a reusable User Defined Action.  Then lets me reuse it in multiple workflows.  What's even better, is when I update the UDA, I can choose to republish all the workflows that currently use this UDA, which updates them all too.

There are however two problems with the UDA:

  • They are scoped at Site, Site Collection or Farm levels, and they are stored with a unique UDA-ID in the Nintex workflow database.
    To share the UDA in two different Site Collections, you have to promote the UDA to the high level Farm scope.

    image
  • Once you have promoted them to Farm level, you can no longer modify them.  Because they are managed via the Central Administration website, and WorkflowDesigner.aspx doesn't work there.

 

A solution

 

The solution I've gone with, which I hated.  Was this:

  • in our development environment, we keep the UDA in the site collection level. 
  • in our production environment, we keep the UDA in the farm level.
  • we modify in development environment via WorkflowDesigner and then we export the UDA and import them in production to override the old version.

 

Con:

  • Dev and Prod aren't the same configuration.
  • You always have to export and import.  You can't change a single setting in production.

I've actually done this for the last 3 years.  At one point, I was so unhappy with this I send meme pictures to the Nintex Workflow team.

clip_image001

 

 

A better solution

 

My colleagues Justin Nash and Bart Bouwhuis told me that actually, I can just hack the WorkflowDesigner.aspx URL and modify a farm level UDA.

For example, here is a Site Collection UDA:

I can modify the farm UDA if I know the WorkflowId and the UdaId.  Well, the UdaId is simple.

Here's a farm level UDA:

You can find the WorkflowId if you export the UDA from Farm, and open it up in a text editor. 
You'd see:  <Id>3c2d163c-41da-4966-90ca-a2727d94ead8</Id>

So combined the two together,

Opens the Farm UDA and lets me modify and publish it.

There is an extra note.

image

When Publishing the UDA, don't click the republish checkbox.  Since that is filtered to workflows only in the current Site Collection.

Instead, after you published your UDA.  Go back to Central Administration.

Click the Analyze UDA Ribbon and Republish from Central Admin.

image

 

A quick SQL view

 

If you can't be bothered digging around for the WorkflowId - you can dump this from Nintex Workflow Database:

 

select
    Name,
    [Description],
    Id,
    StaticId,
    '/_layouts/NintexWorkflow/WorkflowDesigner.aspx?Category=UserDefinedAction&WorkflowId=' + ltrim(StaticId) + '&UdaId=' + ltrim(Id)
from
    NW2010DB.dbo.UserDefinedActions
where
    SiteId is null
and
    WebId is null
   

image

Nintex Form - working with managed metadata fields

 

This is a post I wrote late last year, and applies to the Managed Metadata Fields in Nintex Forms via some "JavaScript middle-tier magic". 

 

Disclaimer

My conversations with the Nintex Form team back then was that at some point they might stop using the SharePoint Managed Metadata Fields and switch to their own control (similar to what they do with the people picker).  Then the following JavaScript code around Managed Metadata fields would stop working.

 

Goals

Nintex has a JavaScript wrapper API (NF.PeoplePickerAPI) around their People Picker Control.

Create something similar that allows me to wrap a Managed Metadata Field.

 

SPG.ManagedMetadataApi

 

(function (SPG, $, undefined) {

    var ctor = function (elem) {
        this.$elem = $(elem);

        var $taxonomyEditor = this.$elem.find(".ms-taxonomy");
        if ($taxonomyEditor.length) {
            this.controlObject = new Microsoft.SharePoint.Taxonomy.ControlObject($taxonomyEditor.get(0));
        }
    };

    ctor.prototype = {

        replaceTerm: function(label, termGuid) {
            var self = this;
            if (self.controlObject == undefined) return;

            var term = new Microsoft.SharePoint.Taxonomy.Term(label + "|" + termGuid);
            self.controlObject.replaceTerm(term);
        },

        clear: function() {
            var self = this;
            self.setRawText("");
        },

        setRawText: function (text) {
            var self = this;
            if (self.controlObject == undefined) return;

            self.controlObject.enableControl(true);
            self.controlObject.setRawText(text);
            self.controlObject.retrieveTerms();
            self.controlObject.validateAll();
        }
    };

    SPG.ManagedMetadataApi = ctor;
})(window.SPG = window.SPG || {}, NWF$);

 

Usage

 

  • List: My List
  • Field: MMField

 

/*
    using "normal" GET REST request doesn't bring back ManagedMetaDataFields, this is a workaround.
    https://social.msdn.microsoft.com/Forums/sharepoint/en-US/92cccd65-ba4c-4870-a858-7cd0e38a0482/how-can-i-use-caml-queries-with-the-rest-api
    because GetItems is a method on the List, this needs to be a POST operation.
*/

var url = _spPageContextInfo.webAbsoluteUrl +
    "/_api/Web/Lists/getByTitle('My List')/GetItems(query=@v1)" +
    "?@v1={'ViewXml':'<View><Query><Where><Eq><FieldRef Name=\"ID\"/><Value Type=\"Integer\">" + siteID +  
    "</Value></Eq></Where></Query></View>'}";

var promise = NWF$.ajax({
    type: "POST",
    url: url,
    headers: {
        "accept": "application/json;odata=verbose",
        "X-RequestDigest": NWF$("#__REQUESTDIGEST").val()
    },
    contentType: "application/json;odata=verbose",
    dataType: "json",
    cache: false,
    processData: true
});

promise.done(function (data) {

    var row = data.d.results[0];

    // similar syntax as NF.PeoplePickerApi
    var $mmField = new SPG.ManagedMetadataApi("#" + fieldMMField);
    $mmField.clear();
    if (row.MMField) {
        $mmField.replaceTerm(row.MMField.Label, row.MMField.TermGuid);
    }
});

taskeng.exe command prompt - get out of my face

 

So I was minding my own business working, and suddenly, a command prompt popped up, blocking my work for a few seconds and then disappeared. 

Very annoying.  Because now I'm distracted.  I need to hunt this thing down.

 

Figure: It can look like this.

 

A quick Bing search reveals that this is actually frequently reported, but most people have the wrong idea to go about fixing this.  They think "oh this is a virus, because I don't know what it was", so I'm going to run anti-virus and just blast away everything.

 

Here's what you should do.

 

Task Engine is Windows' Schedule Tasks.  It is running something.  That something can be a virus, but most likely, something you have installed.

  • So run Task Scheduler
  • Expand the "Task Status" area - this shows you tasks that has run in the selected time period.  You will see there are hundreds of tasks that has ran and will be running.
  • Change the time period filter to the smallest setting "Last hour"
  • Now pick off the single task just just ran.  Moments ago.

image

 

Bingo!

Dell SupportAssistAgent AutoUpdate

 

Task Schedule Library

 

  • Head to Task Schedule Library on the side menu
  • Find the task that's the culprit

 

image

 

Strangely, this app checks for update at 2:33PM every Thursday, right after lunch.  It's been annoying me for nearly a month.  I must have installed it on 13/02/2015.

Now, it's a fairly harmless app doing it update check.  Instead of just disabling the task, I can also:

  • Move the trigger to logon
  • Change the time to 1pm (lunch)
  • Or my favourite - wait for Idle

 

image

 

So, at Thursday 1PM, wait for up to an hour (so between 1pm to 2pm) for my computer to be idle for 15minutes.  Then you can run this app.  When I'm not watching.

 

Perfect

Working with XML in Nintex Workflows (simplified)

 

Problem:

You call an XML web service with Nintex Web Service or Web Request actions.  You get back a lot of XML, and it is very difficult to work with the namespaces getting in your way.

 

Solution:

 

1. Do a quick XSLT post processing in the action, remove all the namespaces with XSLT transform.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">    
<xsl:template match="*">        
    <xsl:element name="{local-name()}">            
    <xsl:apply-templates select="@* | node()" />        
    </xsl:element>
</xsl:template>    
<xsl:template match="@*">        
    <xsl:attribute name="{local-name()}">            
    <xsl:value-of select="." />        
    </xsl:attribute>    
</xsl:template>    
<xsl:template match="text() | comment() | processing-instruction()">
    <xsl:copy />    
</xsl:template>
</xsl:stylesheet>

 

2. Force top level XML node.

This ensures if your service returns multiple top level elements they get wrapped together.

 

3. Use XPath in Query XML Action like this:

/xml/Results/Result/Title

 

Sometimes, after you've wasted half a day working with XML, you just want the simple, no frills, just make it work version.

This will hopefully help you too.

 

Big thanks to Jumpei Yamauchi for helping me with this one.

Feb 2015 CU SP2013: Workflow CurrentSiteUrl is fixed

 

http://support.microsoft.com/KB/2920804

Assume that you create a SharePoint 2013 workflow by using SharePoint Designer 2013, and that the workflow contains an action that retrieves data from the "Current Site URL" field in the "Workflow Context" data source. When you run the workflow, the value retrieved from the "Current Site URL" field is missing a forward slash ("/") at the end of the URL.

 

A few months ago, Microsoft released an update to SharePoint 2013, and it broke many SharePoint Designer Workflows.

If you use the new capabilities in SharePoint 2013 to call REST services, it is very common to concatenate the URL using a combination of the Current Site Url as well as the api/ path.

"http://server/site/" + "_api/web/lists/getbytitle('Announcements')"

The problem is that Microsoft removed the trailing / in the Current Site Url.  This broke many REST calls.

"http://server/site" + "_api/web/lists/getbytitle('Announcements')"

Is no longer valid.  The fix is to reopen all your workflows that are showing this problem, and add a preceding / before _api.  Like this:

"http://server/site" + "/_api/web/lists/getbytitle('Announcements')"

 

Now, with the February 2015 patch, Microsoft is fixing the workflow action again.  Guess what.

"http://server/site/" + "/_api/web/lists/getbytitle('Announcements')"

 

I think this looks dirty

 

Technically, your workflow probably won't break over this.

"http://server/site//_api/web/lists/getbytitle('Announcements')"

Should return you the same values as

"http://server/site/_api/web/lists/getbytitle('Announcements')"

 

But it looks terrible.