Eilene Hao and Gabe Hall here, a program manager and developer on the SPD workflow team; nice to meet you! Today we’d like to answer one of our most frequently asked questions: adding activities into the SPD workflow designer. There’s a more detailed whitepaper describing this in the MOSS SDK’s ECM Starter Kit, but we thought it might be good to give you guys a quick summary, show you another example and give you some tips and tricks to help solve common issues.:)
How does it work?
Before we start with the walkthrough, let’s do a quick rundown of how the SPD workflow designer interacts with actions in SharePoint, so that what we do might make a little more sense.;)
All the actions you see in the SPD workflow designer are activities that live in a DLL on the SharePoint box (e.g. Microsoft.SharePoint.WorkflowActions.dll). There’s a .ACTIONS XML file in the SharePoint TEMPLATE directory on the local file system that describes how to display each of that DLL's activities in a sentence form and bind parameters to the activity’s properties. SPD reads all .ACTIONS files in the directory, then shows all the activities in the designer and pushes the data you enter down into the activity’s properties.
So how do you “import” the activity?
- Create an activity with promoted properties in Visual Studio 2005 called CreateACLTask. This activity is similar to the “Assign a ToDo item” action, except it only assigns to one user, and it restricts permissions on the task so that only the user it’s assigned to can see or edit it.
- Deploy the activity DLL to the Global Assembly Cache (GAC). This will allow SharePoint to load the activity code you wrote.
- Add the DLL to the web.config files. I.e. tell SharePoint that your new activity is safe to use. 🙂
- Create and deploy a .ACTIONS file for the activity to describe the sentence. SPD can read this to know what sentence to create and how to link that sentence into the activity.
Step 1: Creating the activity
This’ll be a pretty basic activity. In Visual Studio, hit File->New->Project and select a workflow activity library. For this action, we’re going to create a task, wait for user to edit the task, and then complete the task. So just 3 activities in sequence: CreateTaskWithContentType, OnTaskChanged, and CompleteTask. Fill out the properties like you normally in a VS workflow.
What’s special about the activity we’re building is that it uses the SpecialPermissions property on CreateTaskWithContentType. This property takes a hashtable of user-permission pairs (e.g. “DOMAIN\john”, SPRoleType). If you bind a hashtable to SpecialPermissions, CreateTaskWithContentType will strip out all existing permissions and only add permissions for each pair you add to the hashtable (if you don’t bind anything to it, it inherits permissions from the task list). So if you wanted only the user the task was ‘assigned to’ to see or edit, you would just say: hashtable.Add(“DOMAIN\john”, SPRoleType.Contributor).
Of course, in this case, we don’t know who this assignee is; he’s specified in SPD, so how do we get that property from the designer?
Enter promoted properties. Promoted properties are properties that are exposed externally to a parent workflow or activity. When SPD generates the parent workflow, the parent workflow passes values through this property into the child activity. Here, we want to get the assignee of the task, so we create a “Dependency Property” with a handy code snippet and name it “Assignee”.
So we bind all the properties on our activity, and now in the CreateTask handler, we’ll use the following code:
private void CreateTask(object sender, EventArgs e)
taskId = Guid.NewGuid();
taskProperties.AssignedTo = Assignee; //Assignee demoted from SPD!
taskProperties.Description = "Complete the task";
taskProperties.Title = "You have a new task";
The last piece of info we need in this activity is the content type for the task. A content type for a workflow tasks is what determine which aspx form to use for editing a task. Have you ever seen the New Task dialog that pops up in SPD when you add an “Assign a Todo” action? This dialog actually creates a new task content type along with an .aspx form to go with it.
So to get the content type, we just need to bind CreateTaskWithContentType’s ContentTypeId property to a promoted property. Rather than use a snippet, this time we can just select create a new property directly from the property binding dialog:
Next, add whatever code you want, and with Assignee and ContentTypeId promoted, we can now deploy it so that you can use it in SPD.
Step 2 and 3: Deploying the DLL and adding it to the authorized types list
Once we’re done with our code, we can compile it and get our DLL. Our DLL should go into the server/web front end’s GAC (%windir%\assembly) so that SharePoint can find and load the activity.
But before SharePoint will run the activity, it has to know that our new dll’s types are safe and trusted so we need to add it to the web.config file. Updating the config file’s authorized types means this activity can be used in declarative workflows in WSS (the workflow equivalent of ‘safe for scripting’). To open this file:
- Open the IIS console.
- Find the web site that is your SharePoint web under the "Web sites" node and select it.
- Right click and choose "Open".
- In the folder window, open the web.config file.
In web.config, browse to the bottom section and look for <System.Workflow.ComponentModel.WorkflowCompiler>. Inside that tag there should be an <authorizedTypes> section and an entry for each set of types. Add your type with the following line of XML:
<authorizedType Assembly="CreateACLTask, Version=22.214.171.124, Culture=neutral, PublicKeyToken=7114224e81918c16" Namespace="CreateACLTask" TypeName="Activity1" Authorized="True" />
Step 4: Creating and adding a .ACTIONS file
Now that our activity can be used by WSS, we have to add it to the actions that SPD can author by adding an entry in a .ACTIONS file. It’s a relatively straightforward XML file; however it has a few moving parts so we will just highlight the important aspects today.
Go to your WSS install directory (typically Program Files/Common Files/Microsoft Shared/web server extensions/12), and find the template/1033/workflow folder. (replace 1033 with the proper language ID if it’s not an English server). Place the following in a new file with the name ‘CreateACLTask.actions’:
<?xml version="1.0" encoding="utf-8"?>
<Actions Sequential="then" Parallel="and">
<Action Name="Assign To-do Item with restricted permissions" ClassName="CreateACLTask.Activity1" Assembly="CreateACLTask, Version=126.96.36.199, Culture=neutral, PublicKeyToken=7114224e81918c16" AppliesTo="all" CreatesTask="true" Category="Task Actions">
<RuleDesigner Sentence="Assign %1 to %2 with restricted permissions">
<FieldBind Field="Title,ContentTypeId" DesignerType="Survey" Text="a to-do item" Id="1"/>
<FieldBind Field="Assignee" DesignerType="SinglePerson" Text="this user" Id="2"/>
<Parameter Name="ContentTypeId" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="Assignee" Type="System.String, mscorlib" Direction="In" />
Essentially, this is a copy of the “Assign To-do item” entry in WSS.ACTIONS with a couple minor changes to the sentence, assembly, and bindings. Now, just do one IISReset and open SPD to create your new locked-task workflows! 🙂
Tip: the most common pitfall is adding a .ACTIONS or web.config entry which doesn’t exactly match your custom DLL. If you find that the action shows up in SPD, but nothing appears when it is selected, verify that the entries you’ve made match the activity class exactly. If a particular binding won’t change, make sure your .ACTIONS field bindings match the promoted properties in your DLL.
In Office 2007, building actions for SPD can be easier and faster than authoring a workflow in Visual Studio. We’ve attached the sample files if you’re interested in taking a closer look.
Good luck and we hope this helps :)!
Eilene and Gabe