Tuesday, September 20, 2011

SharePoint 2010: Workflow Activity to trigger another Workflow

While creating a workflow in SharePoint Designer, You may find a situation in which you may require to create a Step to trigger another workflow on same list. By default its not possible in Sharepoint Designer. So to achieve this we can create a custom workflow activity.

Steps to acheive this
  • Create Empty SharePoint Project.
  • Add Sharepoint Mapped Folder
    "{SharePointRoot}\Template\1033\Workflow"
  • Create new file "SPDStartWorkflow.actions" in mapped folder. And paste below code in this
    <?xml version="1.0" encoding="utf-8" ?>
    <WorkflowInfo>
      <Actions Sequential="then" Parallel="and">
        <Action Name="Start Another Workflow"
         ClassName="WorkflowStarter.StartAnotherWorkflow"
         Assembly="WorkflowStarter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3b0e31fdf8deb757"
         AppliesTo="all"
         Category="Custom Actions">
          <RuleDesigner Sentence="Start another workflow on %2, named %1">
            <FieldBind Field="WorkflowIdentifier" Text="Call Self" Id="1" DesignerType="TextArea" />
            <FieldBind Field="ListId,ListItem" Text="this item" Id="2" DesignerType="ChooseListItem" />
          </RuleDesigner>
          <Parameters>
            <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
            <Parameter Name="WorkflowIdentifier" Type="System.String, mscorlib" Direction="Optional" />
            <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
            <Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" />
          </Parameters>
        </Action>
      </Actions>
    </WorkflowInfo>

  •  Add new class "StartAnotherWorkflow" and inherit it from "Activity". Add below code in file.
        public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context",
                                                                                       typeof(WorkflowContext),
                                                                                       typeof(StartAnotherWorkflow));


        public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string),
                                                                                      typeof(StartAnotherWorkflow));

       
        public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(int),
                                                                                        typeof(StartAnotherWorkflow));

       
       public static DependencyProperty WorkflowIdentifierProperty = DependencyProperty.Register("WorkflowIdentifier",
                                                                                                  typeof(string),
                                                                                                  typeof(
                                                                                                      StartAnotherWorkflow
                                                                                                      ), new PropertyMetadata(""));


        [ValidationOption(ValidationOption.Required)]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public WorkflowContext __Context
        {
            get { return ((WorkflowContext)(base.GetValue(__ContextProperty))); }
            set { base.SetValue(__ContextProperty, value); }
        }

       
        [Description("ID of the list we are working with")]
        [ValidationOption(ValidationOption.Required)]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public string ListId
        {
            get { return ((string)(base.GetValue(ListIdProperty))); }
            set { base.SetValue(ListIdProperty, value); }
        }

       
        [Description("ID of the list item we are working with")]
        [ValidationOption(ValidationOption.Required)]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int ListItem
        {
            get { return ((int)(base.GetValue(ListItemProperty))); }
            set { base.SetValue(ListItemProperty, value); }
        }

       
        [Description("Workflow name or template base id")]
        [ValidationOption(ValidationOption.None)]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public string WorkflowIdentifier
        {
            get { return ((string)(base.GetValue(WorkflowIdentifierProperty))); }
            set { base.SetValue(WorkflowIdentifierProperty, value); }
        }

       
         protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            try
            {
                //need to run under SHAREPOINT\system account because workflow owner might not have start workflow permissions on the target list
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(__Context.Site.ID))
                    {
                        using (SPWeb web = site.AllWebs[__Context.Web.ID])
                        {
                            SPList list = web.Lists[new Guid(ListId)];

                           
                            SPListItem listItem =
                                list.Items.GetItemById(ListItem);

                           
                             //resolve any lookup parameters
                            string wkId =
                                Common.ProcessStringField(executionContext,
                                                          WorkflowIdentifier);

                           
                            //find workflow association by name
                            SPWorkflowAssociation myWorkflowAssoc =
                                list.WorkflowAssociations.GetAssociationByName(
                                    wkId, Thread.CurrentThread.CurrentCulture);
                           
                            if (myWorkflowAssoc != null)
                            {
                                //start the workflow
                                site.WorkflowManager.StartWorkflow(listItem,
                                                                   myWorkflowAssoc,
                                                                   myWorkflowAssoc.AssociationData);
                            }
                        }
                    }
                });
            }
            catch (Exception e)
            {
              
            }

            return ActivityExecutionStatus.Closed;
        }

3 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Will you please provide some sample code Thanks.

    ReplyDelete
  3. nice article! it really helps me to trigger the workflow ! cheers

    ReplyDelete

Popular Posts