Monday, May 23, 2011

Sharepoint 2010 Custom Workflow Activites

(If you're impatient, you can see the code before reading the article)

Sharepoint has a workflow engine, and you can develop workflows for Sharepoint using either Sharepoint Designer or Visual Studio.  Today I'm going to focus on workflows that are created using Sharepoint Designer.  A step in a workflow, such as "Copy item from List A to List B", is called an Activity.

Sharepoint Designer comes with a number of activities out of the box, but you can use Visual Studio to create custom activities that are surfaced to Sharepoint Designer.  For example, if you saw the existing workflow "Copy item from List A to List B", but it wasn't quite what you wanted, you could create a custom activity for "Copy item from List A to List B and List C", and that activity would then show up in Sharepoint Designer when creating a workflow.

Lets dig into how you can create a custom activity for Sharepoint Designer using Visual Studio.


Introduction
There are quite a number of blog posts out there on how to create a custom activity, but most of them talk about using DependencyProperties, which I don't like working with.  Some of them even talk about modifying Sharepoint's XML files, deploying files by hand without a solution, or making manual modifications to web.config, but I wanted to avoid all of those, as they can cause all kinds of problems.  I eventually found a post by Wictor Wilen (and a similar MSDN article) that showed how to create a custom workflow activity in a proper sharepoint solution (WSP) in a much more elegant manner.

I went through that, but it took me a while to get all of the pieces lined up properly, but once I did, I created some sample code so you can see the entire solution and how the pieces fit together.  I'm not going to rehash what Wictor/MSDN said, but rather, I'll add in my comments and caveats from my experiences building a custom activity. 


Sandbox Solution
There are two ways to create custom workflow activities.  From http://msdn.microsoft.com/en-us/library/ff798330.aspx:
- You can create a full-trust workflow activity class and deploy it as a farm solution. To use these activities in SharePoint Designer, you must create and deploy a workflow actions file to package your activity, and you must add an authorized type entry for your activity class to the Web.config file.
- You can create a sandboxed workflow action class and deploy it as a sandboxed solution. To be able to package your workflow action, you must create a feature with a workflow actions element in an element manifest file.

The code I wrote is in a sandbox solution, which is the simpler route.  There are disadvantages to running it as a sandbox solution, including that you are running in partial trust, and there are certain limitations applied to what you can do (although those could be considered an advantage from a security or scalability perspective).

If you need to operate your code in full trust, you can read about the various options at http://msdn.microsoft.com/en-us/library/ff798433.aspx.  Additionally, I will write a follow-up blog post with sample code describing how to call a Sandbox Proxy, thus allowing a sandbox custom activity to perform actions only allowed by full trust.


Parameters
Name Alignment When adding parameters, make sure the names all line up.  There are three things that need to match for each parameter/field.  In my sample code, I used the values of 'FieldName' and 'ExtraString', but you can use whatever you want, so long as they match between the following 3 places:
1. In Elements.xml, there is a 'Field' attribute on each FieldBind element.
2. In Elements.xml, there is a 'Name' attribute on each Parameter element.
3. In Activities.cs, look at the last two parameters on the DoSomething function

Context Parameter There is also the special parameter for context, which provides context for the current operation, such as the current list/list item the workflow is operating on.  Look at the code carefully to see how the parameter is defined in Elements.xml and used in Activities.cs.
  
Out Parameter You can also specify what type of value is returned from your custom activity to Sharepoint Designer.  If you look carefully at this MSDN article, under major step 3, minor step 7, you will see that the RuleDesigner Sentence is "Log Activity (Exception to %1)".  A RuleDesigner sentence is what will show up in Sharepoint Designer when someone adds an activity to a workflow.  When working with activities, out parameters (i.e., return values) are generally indicated by being in parentheses, such as "(Exception to %1)" in this example.  If you look carefully at the code and XML in that article, you will see that the "Except" parameter is defined as an "out" parameter, and that it matches up to the return value of the "Log" function.


Debugging / Logging Errors
As you develop your custom activity, it is inevitable that it will throw exceptions and not work perfectly on your first try.  There are several ways to track down bugs in your code:

1. Debugging
Provided that you have already deployed your code and added it to a workflow, you can open your custom activity project in Visual Studio, add some breakpoints, and hit F5.  If you still have trouble getting debugging working, you can always add a call to System.Diagnostics.Debugger.Launch() in your code, which will pop up a box asking you if you want to debug it.  You can also try to manually attach to all of the SPUC*.exe processes running on your system.

2. Sharepoint Logs 
If an exception is thrown and not caught, and you see something like "Error Occured" in the workflow status, you can often find the real error message and a stack trace in the Sharepoint Logs.  These are found in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Logs.  Additionally, you can use the Sharepoint Logging infrastructure to manually add your own events to these logs.

3. Manually log to Workflow History
If you want something to show up in the Workflow history, you can add a line item there by calling SPWorkflow.CreateHistoryEvent.  To see the workflow history, open the item, click on the 'Workflows' icon for the item, then click on the workflow that you want to see the history for.


Usage
So after creating this solution, how do you use it?
1. Deploy the solution to a Site collection
2. Activate the "My Activity Feature" on your site collection.
3. If Sharepoint Designer is open, close it
4. Open Sharepoint Designer and open the site where you want the workflow
5. Create a workflow.  Click on the 'Actions' button in the ribbon, and you should see "Do My Custom Activity" in the "Custom" category.  Click on it and set its parameter values to something. 
6. Save and deploy the workflow to the site.
7. Open an item on the site.  Click the 'Workflows' link.  Start the custom workflow.

Please note that this particular custom activity uses a Sandbox Proxy that I'll address in a future post.  For now, if you just want it to run, you can comment out that code and put your own code in its place.

 
References:
- Wictor Wilen's Blog Post
http://www.wictorwilen.se/Post/Sandboxed-workflow-activities-in-SharePoint-2010.aspx

- MSDN article with similar content to Wictor's post
http://msdn.microsoft.com/en-us/library/ff798499.aspx#Y1612

- List of Designer Type Attributes
http://developers.de/blogs/nadine_storandt/archive/2008/08/04/deploying-custom-activity-for-sharepoint-designer.aspx

- Codeplex project with other custom workflows
http://spdactivities.codeplex.com

3 comments:

Gary said...

Thank you so much for such a descriptive and clear explanation of breaking through the sandbox with the full trust information. Life saver!

Munir said...

Hi,

Firstly thank you for the post!

If I understand correctly, dont you need an override on the execute function for the workflow activity?

Gary said...

Munir,

It does happen. It is in the ProxyOperations class.