混合 OOTB SPD WFA 和自定义 WFA 时出现问题
我使用的是 MOSS (SharePoint 2007 Enterprise),32 位,SP2。
我注意到我开发并在 SharePoint Designer (SPD) 工作流中使用的自定义工作流活动存在一些奇怪的问题。这些操作似乎可以正常工作,但不能与工作流程的其余部分“很好地配合”(具体来说,根本问题发布在:自定义 WF 活动更改权限的时间问题,因为尚未得到任何回复,所以我一直在深入挖掘...)
以帮助确定问题,我开发了一个非常简单的测试,我将在下面详细概述,并且我注意到这个测试有更多奇怪的行为,这就是我将首先讨论的......
所以,在这个测试结束时我'我有一个简单的 SPD WF,我可以在为此测试创建的列表上手动启动它,其中包含名为“TextField”的单行文本字段/列。 WF 包含执行 4 个操作的 1 个步骤:
- 将字段设置为值(使用我的自定义 WFA 将“1”分配给 TextField 列)
- 将“设置 1”记录到工作流程历史记录列表
- 在当前项目中设置字段(使用 OOTB 操作来将“2”分配给 TextField 列)
- 将“Set 2”记录到工作流历史记录列表
此工作流运行完美,按顺序成功完成工作流消息,并且 TextField==2。
但是,如果我将最后 2 个操作移至操作列表的顶部,则 WF 的单步将如下所示:
- 在当前项目中设置字段(使用 OOTB 操作将“2”分配给TextField 列)
- 将“Set 2”记录到工作流程历史列表
- 将字段设置为值(使用我的自定义 WFA 将“1”分配给 TextField 列)
- 将“Set 1”记录到工作流程历史列表
在本例中,工作流程状态为“错误发生”,即使 TextField==1(第二个分配),工作流历史记录中的唯一项目是:
- 更新列表项时出错
- 设置字段测试中发生错误。
(“Set Field Test”是我的 SPD WF 的名称)
所以,这就是问题的样子:如果我的自定义 WFA 首先发生,则 WF 可以 100% 工作,但每次都会失败(即使字段确实得到正确更新)如果我的自定义 WFA 发生在第二位。我已经多次重复这个测试,包括多次执行动作反转。
我可能在我的自定义 WFA 中做了一些愚蠢的事情,所以这里是(我已将我公司的缩写替换为公共机构 - 获得我的税金的价值)的全部内容:
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;
}
}
}
和我的 .ACTIONS 文件(保存到 C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\Workflow )包含此操作的此条目:
<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>
最后,当然,我的 web.config 包含我的程序集的条目。
当然,这是一个非常简单的操作,但即使它在我的 SPD WF 中也无法正常工作。我肯定做错了什么,但我能找到的有关创建自定义 WFA 的所有文档都使这看起来是正确的。任何人都可以看到我的代码中的问题,甚至可以在您自己的环境中尝试一下吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我已经在我的开源项目中实际解决了这个问题。从 http://spdactivities.codeplex.com/ 下载源代码并查看其中之一的源代码许可活动。您的代码不起作用的原因是 OOTB 活动参与事务,而您的自定义活动不参与。这就是您的自定义活动在所有 OOTB 活动之前运行的原因。
要参与工作流程,您需要实施 IPendingWork 并提交到 WorkflowEnvironment.WorkBatch。华泰
I have acually solved this problem in my open source project. Download the source code from http://spdactivities.codeplex.com/ and look at the source for one of the permission activities. The reason your code does not work is because the OOTB activities participate in a transaction and your custom activity does not. That is why your custom activity runs before all OOTB activities.
To participate in the workflow you need to implement IPendingWork and submit to WorkflowEnvironment.WorkBatch. HTH