Creating a dynamic custom activity in SharePoint 2013

In a recent project, I needed to create some custom workflow activities, to expose functionality in workflows. As we are using SharePoint 2013, the best way forward was to use the new SharePoint 2013 workflow. There is a possibility to use a code activity, there is some extra deployment needed, but using HttpSend and adding the code to a wcf rest service seemed a better option to me.

Some of the requirements where to support still unknown (jet to be configured) actions. One of these needed a dynamic range of properties to be send to an external system, an other needed retrieving attributes, but these attributes needed to be flexible based on the retrieval action. For all of these, a flexible solution was needed, so that the custom activity and underlying wcf service doesn't need updating when adding/configuring new options.

Here I will show you how I achieved implementing these requirements, using a custom activity and a wcf rest service. As wcf services have a fixed data contract, I needed a trick to get things working dynamically.

Just to note, I am not that into workflow. For me as a developer/programmer I have the need to write code, and not to configure/develop a workflow using SharePoint designer. I do see that workflow is powerful, but I know that others are much better and more experienced in developing workflows, and it's just not my thing. That said, developing a custom activity using a wcf rest service, is more in line with what I do as a developer.

I will describe the trick used by me and take advantage of the new DynamicValue type. The trick used is the main focus here, but you can download a full working sample solution.

A wcf rest service was created. For the dynamic properties send to the service, and the dynamic attributes retrieved, I use a string value in the interface exposed by this service.

[DataContract]
public class DynamicRequest
{
    [DataMember]
    public string Action { get; set; }

    [DataMember]
    public string Parameters { get; set; }
}
    

To call the service, I retrieve the current site url and create a DynamicValue containing Action and Parameters. I set these values to the values received as input arguments from the custom activity. The parameters received are of the type DynamicValue, now the trick is to use a .ToString() to get the json as a string. This DynamicValue is set as the RequestContent in the HttpSend.

trick Dynamic Parameters

The json string value can then be deserialized to a Dictionary<string, object> by the wcf service and the parameters can then be used in the subsequent code.

JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, object> parameters = (Dictionary<string, object>)serializer.DeserializeObject(request.Parameters);
    

You will have to check the existence of the named parameters yourself, and also do the appropriate parsing.

To receive attributes dynamically a similar solution can be used, this time serializing a Dictionary<string, string> object to a string. In my example I just use this string as the return value. This value is then received as the ResponseContent in a string variable. Now we have to extract the json value from this string, I use a simple substring and replace here: ResponseContent.Substring(1, ResponseContent.Length - 2).Replace("\\", ""), and parse this using the ParseDynamicValue, setting the result to the output argument of the type DynamicValue.

Dictionary<string, string> dynamicValues = new Dictionary<string, string>();
// some code adding values
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(dynamicValues);
    
trick Dynamic Attributes

Now if you build and deploy the sample solution, and activate the feature, you can use these custom activities in SharePoint designer, and play around with the different actions.

First sample workflow (the site uses a Dutch language pack):

first sample workflow

Then you can see the properties send using the debugger:

breakpoint

Second sample workflow (again the site uses a Dutch language pack):

second sample workflow

Now you can see the value of the specified attribute 'AttributeTwo' in the history.

workflow history

I hope you can now see that having an option to use dynamic properties when executing an action, or retrieving a dynamic set of values, can be very powerful. You can also use the dynamic properties when executing an action to retrieve dynamic attributes, if you want. Of course the dynamic values used or retrieved must be predictable, that is why I use an action identifier. Also note that making everything this dynamic isn't needed most of the time.

Some references I have used:
SharePoint 2013 Workflow: Use HttpSend Activity to call Custom SharePoint WCF Service
SharePoint 2013 Workflow Development - Handling Dynamic Values and Collections

One thing to note, I have added a request header Authorization with the value "" (empty string) to ensure authentication when calling the wcf service.

calling wcf service

Another thing is, if you wish to debug the calling of the wcf rest services, log on to your machine (remote desktop) using the account used by your workflow service application and then you can use Fiddler to see what is going on at the request and response levels when starting the workflow.

One additional note, if you see that authentication keeps on failing when the workflow custom activity contacts the wcf rest service (you can see this using Fiddler), there is a setting in the registry that might help you out. It is called 'DisableLoopbackCheck', here you can find how you can set (or check) the value. This works if the workflow service is running on the same server as the web front-end. Hope this saves you the trouble of figuring out what is going wrong. Please also take a look at http://support.microsoft.com/kb/896861 as this explains that you might want to set this differently on production environments. Still, 'Method 1' might need extra manual configuration when a new web application is created.

Update 2014/10/31

Recently I discovered that there was an issue with my dynamic custom activity. It seems that a SharePoint update affected the look-up workflow context property Current Site URL. It now seems to miss the / at the end. I know that I wanted to add a check for this when creating this, as in code I use CombineUrl, but I skipped this. What I have learned from this is also to use defensive programming/configuration in a custom workflow activity. I now have added a check for the / and this solved the issue.

added if statement

I have updated the sample solution you can download above, to include this fix for changed SharePoint behavior.