从其他SharePoint工作流程序化调用SharePoint工作流实例

[原文发表地址]Calling SharePoint workflow instances programmatically from other SharePoint workflows (Justin Joyce)

[原文发表时间]2011-08-23 07:00

概述:

我们的客户列出了一系列需要工作流的项。其中的一些由于特定域值和条件会比其他的流更长。一些其他的特定类型项只要几个步骤,然后就会退出流再不回来。

介于这个要求,我们决定使用列表上的两个工作流。主要工作流负责项的创建,执行初始化新列表项所需的常规行为,包括设置唯一属性项ID代码,收集项上初始准许。第二工作流由第一工作流调用,即当特定域值存在,而且项是特定内容类型。

这就产生了一些有趣的问题,比如我们要怎么来完成这个。我们考虑的主要问题在于找到正确的工作流来启动项。我们不能确保实例名称总是我们设置的那个,因为客户会进来可以根据他们的喜好进行变更。由于现在已经有两个工作流模板附在列表上了,我们就不能使用首页属性。

实行:

那么是什么用独特有用的方式在认证工作流模板呢?每一个工作流模板都有一个基本模板ID号,以GUID的形式存在, 给了它一个独特的标识。附加在特定列表的工作流模板通过.BaseID属性保留这个基本模板ID号。啊哈!所以现在我们可以识别目标了。那么最简单的找到适合BaseID属性的GUID方法是什么呢?在我的例子中,介于我开发了两个工作流,所以我可以访问所有代码,进入项目的目标工作流,打开Elements.XML文件(如果你没有源代码,你也可以从工作流的Elements.xml文件中获取这个值,通过以下路径就行了:C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES\FeatureName\WorkflowName\Elements.xml),下面你会看到工作流节点上的Id属性,就是你的基本模板Id。

clip_image002

现在我们知道我们要找什么了,但是我们要怎么找呢?显然是通过最好的LINQ.

我们正在运行的父列表有一个属性叫做WorkflowAssociations,你可能已经猜到这是可以用LINQ查询到的SPWorkflowAssociation对象的一个集合。

http://msdn.microsoft.com/EN-US/library/ms462802

现在还有一个要注意的地方,可能会出现目标工作流需要更新或者在某些点改变,而同时允许现有工作流实例存在,忽略它们其实已经被最新最好的取代的事实。这样你就要进入设置列表的工作流,将旧的工作流设置为“没有新实例”,然后附上最新的改良版。这就留下了一个潜在问题,我们必须在LINQ询问中要对其解释。由于这些工作流实例可能有相同的基本模板Id,它们可能都满足以下询问标准:

   1: Guid svpwfid = new Guid("4e126fc9-6b12-1212-8c21-21120f264bad");

   2: var wfa = (from SPWorkflowAssociation spwfa in workflowProperties.Item.ParentList.WorkflowAssociations

   3:            where spwfa.BaseId == svpwfid

   4:            select spwfa).FirstOrDefault();

现在看看SPWorkflowAssociation类的成员,像NoNewInstances这样的属性名称是不会跳出什么东西的。

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.workflow.spworkflowassociation_members.aspx

不过有Enabled属性。当你设置附到列表的工作流为没有新实例时,Enabled属性就会是False。因此我们最小化调整LINQ查询,我们可以确认只有调回的结果才是工作流相关模板,即符合我们的基本模板Id,同时允许在特定列表上启动新实例。

   1: Guid svpwfid = new Guid("4e126fc9-6b12-1212-8c21-21120f264bad");

   2: var wfa = (from SPWorkflowAssociation spwfa in workflowProperties.Item.ParentList.WorkflowAssociations

   3:            where spwfa.BaseId == svpwfid && spwfa.Enabled == true

   4:            select spwfa).FirstOrDefault();

既然我们有了查询来获取适合的工作流相关模板,我们就能实例化SPWorkflowManager对象了。并传给工作流相关,相关数据,我们的列表项和bool flag以通过StartWorkflow()函数自动启动属性。

整体实行如下:

   1: Guid svpwfid = new Guid("4e126fc9-6b12-1212-8c21-21120f264bad");

   2: var wfa = (from SPWorkflowAssociation spwfa in workflowProperties.Item.ParentList.WorkflowAssociations

   3:            where spwfa.BaseId == svpwfid && spwfa.Enabled == true

   4:            select spwfa).FirstOrDefault();

   5:  

   6: if (wfa != null)

   7: {

   8:     SPWorkflowManager wfMan = workflowProperties.Item.ParentList.ParentWeb.Site.WorkflowManager;

   9:     wfMan.StartWorkflow(workflowProperties.Item, wfa, wfa.AssociationData, true);

  10: }

  11: else

  12: {

  13:     // could not find workflow template.

  14: }

总结:

这就是你如何从一个工作流找到并启动另一个工作流了。这个代码可以做适当的小小的变化,适应各种其他类型的与SharePoint相关的应用。只是需要做些工作来获取列表,列表项和页面,因为你无法进入工作流上下文。

Justin Joyce

发表评论