Office Sharepoint Designer 2007 Custom Action

This article describes how to create a custom action that will appear in the Workflow dialog in the Office Sharepoint Designer 2007 client. The example in the walkthrough is created using C#.

Create a new Visual Studio project based on the Workflow Activity Library project template. If you have Visual Studio 2008 this template will be available by default, if you’re using Visual Studio 2005 then you’ll need to install the Extensions for the .NET Framework 3.0 (Windows Workflow Foundation) available here.

If you need to use the backend Sharepoint classes then you will need to add a reference to the following files from the Sharepoint server. If your not working directly on the server take a local copy of them:

c:\program files\common files\microsoft shared\web server extensions\12\isapi\microsoft.sharepoint.dll
c:\program files\common files\microsoft shared\web server extensions\12\isapi\microsoft.sharepoint.workflowactions.dll

Edit the code behind the Activity1.cs.

Add the following using statements to include the Sharepoint classes from the files we referenced.
using Microsoft.SharePoint.WorkflowActions;
using Microsoft.SharePoint;
Here’s the main body of the code behind in Activity1.cs
public partial class Activity1 : SequenceActivity
{
public Activity1()
{
InitializeComponent();
}

/// 
/// User data from the sharepoint desginer workflow.
/// 
public static DependencyProperty ItemProperty = DependencyProperty.Register("Item", typeof(string), typeof(Activity1));
/// 
/// The workflow context object.
/// 
public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(Activity1));
/// 
/// The name of the SPList the workflow is executing on.
/// 
public static DependencyProperty __ListIdProperty = DependencyProperty.Register("__ListId", typeof(string), typeof(Activity1));
//
/// 
/// The integer value of the list item in the list that the workflow is running on.
/// 
public static DependencyProperty __ListItemProperty = DependencyProperty.Register("__ListItem", typeof(int), typeof(Activity1));

/// 
/// User data from the Sharepoint Designer workflow.
/// 
[ValidationOption(ValidationOption.Required)]
public string Item
{
get
{
return ((string)(base.GetValue(Activity1.ItemProperty)));
}
set
{
base.SetValue(Activity1.ItemProperty, value);
}
}

/// 
/// The workflow context object.
/// 
[ValidationOption(ValidationOption.Required)]
public WorkflowContext __Context
{

get
{
return ((WorkflowContext)(base.GetValue(Activity1.__ContextProperty)));
}
set
{
base.SetValue(Activity1.__ContextProperty, value);
}
}

/// 
/// The name of the SPList the workflow is executing on.
/// 
[ValidationOption(ValidationOption.Required)]
public int __ListItem
{
get
{
return ((int)(base.GetValue(Activity1.__ListItemProperty)));
}
set
{
base.SetValue(Activity1.__ListItemProperty, value);
}

}

/// 
/// The integer value of the list item in the list that the workflow is running on.
/// 
[ValidationOption(ValidationOption.Required)]
public string __ListId
{
get
{
return ((string)(base.GetValue(Activity1.__ListIdProperty)));
}
set
{
base.SetValue(Activity1.__ListIdProperty, value);
}

}

/// 
/// The Execute method contains the code that runs
/// 
/// ActivityExecutionContext object/// ActivityExecutionStatus enumerator
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
try
{
// Get the list in which this workflow was started.
SPList list = __Context.Web.Lists[new Guid(__ListId)];

// Get the item that has triggered the workflow.
SPListItem item = list.Items.GetItemById(__ListItem);

//Write your code here
}
catch (Exception ex)
{
//Create an application event log source to log any errors to.
if (!System.Diagnostics.EventLog.SourceExists("ActivityLibrary")) System.Diagnostics.EventLog.CreateEventSource("ActivityLibrary", "Application");
EventLog.WriteEntry("ActivityLibrary", ex.Message, EventLogEntryType.Error);
}
//Set the ActivityExecutionStatus to Closed to complete the acitvity.
return ActivityExecutionStatus.Closed;
}
}

If you want to write to the Event Log on the server you will need to grant permission in the registry to the account that is running the sharepoint application pool. Edit the permissions of the following registry key and grant the NETWORK SERVICE account Full Control:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application

We will need to install this assembly into the Global Assembly Cache (GAC) on the Sharepoint server, so it will need to be signed with a strong name. Edit the project properties and goto the Signing tab, check the “Sign the assembly” box and create a new strong name key file.

Build the project and copy the resulting dll file to into the c:\windows\assemblies folder on the Sharepoint server using windows explorer, this will install the assembly into the GAC. If your not working directly on the server you will not be able to copy the dll directly into the assemblies folder remotely, so copy it to a shared folder on the server first.

Make a note of the public key given to the dll file as it will be needed. The easiest way to do this is to right click the assembly in the c:\windows\assemblies folder and examine its properties, you can then copy the public key into the clipboard.

Copy the XML Document below and save it to following file location on the Sharepoint server:

C:\program files\common files\microsoft shared\web server extentions\12\template\1033\workflow\workflowactivitylibrary.actions
<?xml version="1.0" encoding="utf-8"?>
<WorkflowInfo>
<Actions Sequential="then" Parallel="and">
<Action Name="The name of the Action"
ClassName="WorkflowActivityLibrary.Activity1"
Assembly="WorkflowActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8a547c1061ba62ad"
AppliesTo="list"
Category="Custom Actions"
UsesCurrentItem="true">
<RuleDesigner Sentence="Perform custom action with this text %1">
<FieldBind Field="Item" Text="message" DesignerType="TextArea" Id="1"/>
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In" />
<Parameter Name="__ListId" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="__ListItem" Type="System.Int32, mscorlib" Direction="In" />
</Parameters>
</Action>
</Actions>
</WorkflowInfo>

You can create Rules to collect information from the user creating the workflow in the Sharepoint Designer client. Here’s a link to the Workflow Actions Schema documentation on MSDN.

Finally we need to let Sharepoint know that our assembly is safe to use by editing the web.config file in the c:\inetput\wwwroot\wss\virtualdirectories\80 folder on the Sharepoint server.

Add the following snippet into the web.config file:
<configuration>
<System.Workflow.ComponentModel.WorkflowCompiler>
<authorizedTypes>
<authorizedType Assembly="WorkflowActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8a547c1061ba62ad" Namespace="ActivityLibrary" TypeName="*" Authorized="True" />
</authorizedTypes>
</System.Workflow.ComponentModel.WorkflowCompiler>
</configuration>
Now restart IIS on the Sharepoint server, and create or edit an existing workflow in the Sharepoint Designer client. You should now see your custom action !

If you need to make changes to the code, you only need to recompile and update the assembly in the GAC on the Sharepoint server.

0 comments: