I'm using MOSS (SharePoint 2007 Enterprise), 32-bit, SP2.
I've been noticing some odd problems with Custom Workflow Activities which I've developed and am using in SharePoint Designer (SPD) workflows. These actions seem to work correctly, but don't "play nice" with the rest of the workflow (specifically, the root issue was posted at: Timing concerns with Custom WF Activity changing permissions , since that hasn't gotten any responses I've been digging deeper...)
To help pin down the problem, I've developed a very simple test, which I will outline in detail below, and am noticing even more odd behavior with this test, which is what I'll get into first...
So, at the end of this test I've got a simple SPD WF which I can start manually on a list I created for this test, which contains a Single Line of Text field/column named "TextField". The WF contains 1 step which performs 4 actions:
- Set Field to Value (uses my custom WFA to assign "1" to the TextField column)
- Log "Set 1" to the workflow history list
- Set Field in Current Item (uses the OOTB action to assign "2" to the TextField column)
- Log "Set 2" to the workflow history list
This workflow runs perfectly, completing successfully with the workflow messages in order, and TextField==2.
However, if I move the last 2 actions to the top of the actions list, making the WF's single step then look like:
- Set Field in Current Item (uses the OOTB action to assign "2" to the TextField column)
- Log "Set 2" to the workflow history list
- Set Field to Value (uses my custom WFA to assign "1" to the TextField column)
- Log "Set 1" to the workflow history list
In this case, the workflow status is "Error Occurred", and even though TextField==1 (the second assignment) the only items in the workflow history are:
- Error updating a list item
- An error has occured in Set Field Test.
("Set Field Test" is the name of my SPD WF)
So, that's what the problem looks like: The WF works 100% if my custom WFA happens first, but fails every time (even though the field does get updated correctly) if my custom WFA happens second. I've repeated this test many times, including to perform the action reversal multiple times.
I might be doing something dumb in my custom WFA, so here it is (I've replaced my company's acronym with public agency - getting my tax dollars' worth) in its entirety:
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Reflection;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
namespace NASA.workflowActivity {
public partial class TestSetFieldValueActivity : Activity {
#region Dependency Properties
public static DependencyProperty itemFieldProperty = DependencyProperty.Register("itemField", typeof(String), typeof(TestSetFieldValueActivity));
public static DependencyProperty newValueProperty = DependencyProperty.Register("newValue", typeof(String), typeof(TestSetFieldValueActivity));
public static DependencyProperty __ActivationPropertiesProperty = DependencyProperty.Register("__ActivationProperties", typeof(Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties), typeof(TestSetFieldValueActivity));
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
public String itemField {
get { return base.GetValue(TestSetFieldValueActivity.itemFieldProperty).ToString(); }
set { base.SetValue(TestSetFieldValueActivity.itemFieldProperty, value); }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
public String newValue {
get { return base.GetValue(TestSetFieldValueActivity.newValueProperty).ToString(); }
set { base.SetValue(TestSetFieldValueActivity.newValueProperty, value); }
}
[ValidationOption(ValidationOption.Required)]
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties __ActivationProperties {
get { return (Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties)base.GetValue(TestSetFieldValueActivity.__ActivationPropertiesProperty); }
set { base.SetValue(TestSetFieldValueActivity.__ActivationPropertiesProperty, value); }
}
#endregion
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) {
try {
SPListItem listItem = this.__ActivationProperties.Item;
SPField field = listItem.Fields[this.itemField];
listItem[field.Id] = this.newValue;
listItem.SystemUpdate();
} catch {
return ActivityExecutionStatus.Faulting;
}
return ActivityExecutionStatus.Closed;
}
}
}
And my .ACTIONS file (saved to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\Workflow ) contains this entry for this action:
<Action
Name="Set field in current item (Custom WFA)"
ClassName="NASA.workflowActivity.TestSetFieldValueActivity"
Assembly="NASA.workflowActivity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f579ebeb24170bf5"
AppliesTo="all"
Category="NASA WFA: Test">
<RuleDesigner Sentence="Set %1 to %2 (Custom WFA)">
<FieldBind Id="1" Field="itemField" DesignerType="FieldNames" text="field" />
<FieldBind Id="2" Field="newValue" DesignerType="Text" text="value" />
</RuleDesigner>
<Parameters>
<Parameter Name="itemField" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="newValue" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="__ActivationProperties" Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint" Direction="In" />
</Parameters>
</Action>
And finally, of course, my web.config contains an entry for my assembly.
This is a very simple action of course, but even it isn't working right in my SPD WF. I must be doing something wrong, but all the documentation I can find on creating a custom WFA makes this look correct. Can anyone see a problem in my code, or even try this out in your own environment?