Tuesday, 18 October 2011

Custom Workflow Actions in SharePoint 2010

On a recent SharePoint 2010 project I had the opportunity to look at creating custom Workflow​ Actions which is a way to extend the actions already available in SharePoint Designer Workflows.
If I'm honest, the foray was both informative and slightly arduous but perhaps due mostly to my own inability to type properly and my own lack of understanding. Let's start by having a look at why we decided to look down this path.

Why a Custom Workflow Action?

The project in question required a handful of workflows to be developed, all of which were prepared and written using SharePoint Designer. The problem was highlighted early on that we needed to port the be able to package the workflows up to deliver them across multiple platforms during the development life-cycle.

For 2 of the workflows, this didn't pose a problem since they were Reusable Workflows which lend themselves to just this kind of functionality. The 2 workflow, however, was a List-based workflow and as such it was not able to be exported as a WSP. The reason the workflow was a List-based workflow was due to the columns necessary to facilitate the workflow actions - Approval Status being the culprit in this scenario. As it turns out, the "Approval Status" column is not visible for anything other than a List-based workflow.

To allow the workflow to be packaged up meant it had to be a Reusable Workflow, or we had to provide a work-around. After several attempts to package the workflow up (using this method http://ikarstein.wordpress.com/2011/02/10/walkthrough-how-to-move-or-copy-a-sharepoint-designer-2010-list-workflow-to-another-list-on-the-same-site-or-another-site/ was a way to export a List-based workflow using the "Export to Visio" and "Import from Visio" options which did work but didn't provide the hands-off approach we wanted) we decided to try writing a custom Workflow Action to perform the steps we required.

Nuts and Bolts

As it turns out, creating a custom Workflow Action is pretty straight-forward. Create a class, create a publicly declared static method in the class, and away you go. The first parameter must be a context object - we were deploying as a User Code Solution so this was of type SPUserCodeWorkflowContext.

If you're action doesn't need any parameters, do your coding stuff and then move on to the feature XML.

One note here - any typos or spelling mistakes mean that your workflow will not run. I battled for a long time to debug my workflow with only frustration as my reward. I eventually searched the SharePoint logs and found that I had mis-named a parameter so my workflow was never being run. Once I had fixed that, I was away after I had attached to the SharePoint User Code process.
Here's a couple of walk-throughs I found: http://msdn.microsoft.com/en-us/library/gg615449.aspx and http://msdn.microsoft.com/en-us/library/ff798499.aspx. What I would say is that the first article is more accurate. The second one makes no mention of the fact that the method you implement for your action should be a static method - even the example code doesn't show this, so beware.

End-to-end, the final solution (which wasn't overly complicated) took about a day, and at the end I had a fully working custom workflow action which I could use in my workflows. Looking back, it was actually quite painless and easy and once you know where to look (i.e. SharePoint logs, debugging etc) it was fairly rapid.

The Fairytale Ending(?)

Unfortunately, there is no happy ending to this story. I went through a day of trauma and frustration and came out the other side having happily implemented my custom workflow action into a reusable workflow. I saved the workflow through SharePoint Designer to a WSP and thought things were making sense.

I then moved the workflow to another site collection and installed the WSP and that's where the story currently ends. It didn't work. Well.....I say that it didn't work, but I don't really know if I'm honest. The only definition I have to say it didn't work is the fact that the workflow I had created did not appear anywhere so I was unable to use it. No doubt I will post further about this once I've figured out what went wrong here.

Final Thoughts

Looking back at the reasons behind our decision to use a workflow it was mostly dictated by the approach to the required functionality we had already started: namely the other 2 reusable workflows. Keeping to the same model for the third workflow made sense as it followed the same technology instead of departing in a different direction and introducing custom code instead of manully created workflow (i.e. event receivers).

As it turned out, writing a custom workflow action still meant code in order to achieve the portability we wanted so at that point, perhaps, it would have been better to write an event receiver. The influence to stick with workflow came from the technology angle - keeping to the same "hymn sheet" as it were. Yes, it was custom code, but at least it was still workflow.

Fortunately, in this scenario we did have a fallback position to backup the site and restore it, so the time invested was as much for research into this area, which, if I'm honest, was time well spent.

No comments:

Post a Comment