1. Try to do it without coding;
2. If we have to write some code, try to put them into a workflow activity, then call it from SharePoint designer workflow; (for sequential workflow, of course)
Workflow activity also conforms to my favorite coding principle: Modulization. This means, the code in a workflow activity doesn't rely much on other modules in the system, and we don't need to copy the code to other place to implement similar functionality.
In parallel block of SharePoint designer workflow, sometimes we need the task ID which is just created by the other block. Below is the main source code of that activity.
To get the .wsp file, please visit http://efspwfactivities.codeplex.com
------------------getRelevantTaskID.actions
<?xml version="1.0" encoding="utf-8" ?>
<WorkflowInfo>
<Actions Sequential="then" Parallel="and">
<Action Name="get task id which connected to the current item"
ClassName="EFSPWFActivities.getRelevantTaskID"
Assembly="EFSPWFActivities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=acba72888faca36a"
AppliesTo="all"
Category="EF Workflow Activities">
<RuleDesigner Sentence="put User Login name list from user group %1 to %2.">
<FieldBind Field="TaskListName" Text="task list name" DesignerType="ListNames" Id="1"/>
<FieldBind Field="TaskID" Text="Task ID" DesignerType="ParameterNames" Id="2"/>
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In" />
<Parameter Name="__ActivationProperties" Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint" Direction="In" />
<Parameter Name="__ListId" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="__ListItem" Type="System.Int32, mscorlib" Direction="In" />
<Parameter Name="TaskListName" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="TaskID" Type="System.String, mscorlib" Direction="Out" />
</Parameters>
</Action>
</Actions>
</WorkflowInfo>
------------------getRelevantTaskID.cs
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
bool bReturn = false;
SPList objSPListTask = null;
SPList objSPListCurrent = null;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
objSPListCurrent = __Context.Web.Lists[new Guid(__ListId)];
objSPListTask = __Context.Web.Lists[new Guid(TaskListName)];
SPQuery qry = new SPQuery();
qry.RowLimit = 1;
qry.Query = string.Format("<OrderBy><FieldRef Name='ID' Ascending='False'/></OrderBy><Where><Eq><FieldRef Name='WorkflowItemId' /><Value Type='Text'>{0}</Value></Eq></Where>", __ListItem);
SPListItemCollection items = objSPListTask.GetItems(qry);
if (items.Count == 1)
{
TaskID = items[0].ID.ToString();
WriteDebugInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, string.Format(@"TaskID = {0}", TaskID));
bReturn = true;
}
else
{
WriteDebugInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, "No relevant task found.");
bReturn = false;
}
});
if (bReturn == false)
{
return ActivityExecutionStatus.Faulting;
}
}
catch (Exception ex)
{
WriteDebugInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, string.Format(@"ex.Message = {0}, ex.StackTrace = {1}", ex.Message, ex.StackTrace));
return ActivityExecutionStatus.Faulting;
}
return ActivityExecutionStatus.Closed;
}
Hi Eric,
ReplyDeleteIt sounds interesting. We use the OOTB Approval Process to assign parallel approval tasks to 5 groups. However, with sharepoint designer workflow, we can only capture the last task id. Is your code able to capture all task ids? Thanks.
I am afraid not. SharePoint 2010 declarative workflow can only handle simple requirement. In your case, you may have to consider coding.
ReplyDelete