Introduction

This blog post will show you how to start a workflow programmatically every time an item is updated in a SharePoint list. For those who don’t know, Windows Workflow Foundation (WF) is the new engine for building custom workflows (you can find more information about WF on the official web site). It was released as part of the .NET Framework 3.0 along with Windows Presentation Foundation (WPF) and Windows Communication Foundation (WCF). In the SharePoint world, workflows can be associated both to a list and to a content type. Both options are valid and the choice for one or the other option depends on your needs:

  • If you want to run a workflow in a list, independently of the content type of each list item, you should associate the workflow to a list. If you have more than one content type associated to the list, care should be taken in the workflow implementation since each content type can have different columns that may not be present in the other content types;
  • If you want to run the workflow on all items of a specific content type, you should associate the workflow to a content type. The workflow will be associated to all list items from that content type in all lists across a site or the whole site collection (depending on the scope of the workflow, typically defined in its deployment feature) that are associated with the content type.

Example

The following example shows how both options can be addressed. This example uses an event handler and starts a workflow every time an item is updated in a SharePoint list.


public class ProgrammaticWorkflowInitiationEventReceiver : SPItemEventReceiver
{
    /// <summary>
    /// Event handler for item updated event.
    /// </summary>
    /// <param name="properties"></param>
    public override void ItemUpdated(SPItemEventProperties properties)
    {
        //use this method if the workflow is associated to a list
        StartListWorkflow(properties);

        //use this method if the workflow is associated to a content type
        StartContentTypeWorkflow(properties);
    }

    /// <summary>
    /// Starts a workflow associated to a list programmatically.
    /// </summary>
    /// <param name="properties"></param>
    private void StartListWorkflow(SPItemEventProperties properties)
    {
        //get list item from event handler properties
        SPListItem listItem = properties.ListItem;

        using (SPWeb web = listItem.Web)
        {
            using (SPSite site = web.Site)
            {
                //obtain an instance of SPWorkflowManager 
                //which will be later used to start the workflow
                SPWorkflowManager manager = site.WorkflowManager;
                //get item's parent list
                SPList parentList = listItem.ParentList;
                //get all workflows that are associated with the list
                SPWorkflowAssociationCollection associationCollection = 
                    parentList.WorkflowAssociations;
                //lookup and start the worflow
                LookupAndStartWorkflow(listItem, manager,
                    associationCollection, "FDEDCC37-4D8A-44ba-8E22-57B2669A887C");
            }
        }
    }

    /// <summary>
    /// Starts a workflow associated to a content type programmatically.
    /// </summary>
    /// <param name="properties"></param>
    private void StartContentTypeWorkflow(SPItemEventProperties properties)
    {
        //get list item from event handler properties
        SPListItem listItem = properties.ListItem;

        using (SPWeb web = listItem.Web)
        {
            using (SPSite site = web.Site)
            {
                //obtain an instance of SPWorkflowManager 
                //which will be later used to start the workflow
                SPWorkflowManager manager = site.WorkflowManager;
                //get item's content type
                SPContentType contentType = listItem.ContentType;
                //get all workflows that are associated with the content type
                SPWorkflowAssociationCollection associationCollection = 
                    contentType.WorkflowAssociations;
                //lookup and start the worflow
                LookupAndStartWorkflow(listItem, manager,
                    associationCollection, "FDEDCC37-4D8A-44ba-8E22-57B2669A887C");
            }
        }
    }

    /// <summary>
    /// Lookup and start the workflow.
    /// </summary>
    /// <param name="listItem"></param>
    /// <param name="manager"></param>
    /// <param name="associationCollection"></param>
    /// <param name="workflowId"></param>
    private static void LookupAndStartWorkflow(SPListItem listItem, 
        SPWorkflowManager manager, 
        SPWorkflowAssociationCollection associationCollection, 
        string workflowId)
    {
        //iterate workflow associations and lookup the workflow to be started
        foreach (SPWorkflowAssociation association in associationCollection)
        {
            //if the workflow association matches the workflow we are looking for,
            //get its association data and start the workflow
            Guid workflowGuid = new Guid(workflowId);
            if (association.BaseId == workflowGuid)
            {
                //get workflow association data
                string data = association.AssociationData;

                //start workflow
                SPWorkflow wf = manager.StartWorkflow(listItem, association, data);
            }
        }
    }
}

In the previous example, the following actions are being performed:

  • The ItemUpdated event in the event handler is being handled. For demonstration purposes, I am assuming that two workflow associations were created, one to a list and another to a content type;
  • A call is made to the StartListWorkflow method, which starts the workflow associated with a list;
  • A call is made to the StartContentTypeWorkflow method, which starts the workflow associated with a content type.

Related Articles

To learn why your business should migrate to SharePoint Online and Office 365, click here and here.

If you want to convert your tenant’s root classic site into a modern SharePoint site, click here.

If you are a SharePoint administrator or a SharePoint developer who wants to learn more about how to install a SharePoint farm in an automated way using PowerShell, I invite you to click here and here. The articles use AutoSPInstaller with a SharePoint 2016 farm but AutoSPInstaller support for SharePoint 2019 was already announced!

If you want to learn how to upgrade a SharePoint 2013 farm to SharePoint 2019, click here and here.

If you want to learn all the steps and precautions necessary to successfully keep your SharePoint farm updated and be ready to start your move to the cloud, click here.

If you learn how to greatly speed up your SharePoint farm update process to ensure your SharePoint farm keeps updated and you stay one step closer to start your move to the cloud, click here.

If you want to learn how to upgrade a SharePoint 2010 farm to SharePoint 2016, click here and here.

If you are new to SharePoint and Office 365 and want to learn all about it, take a look at these learning resources.

If you are work in a large organization who is using Office 365 or thinking to move to Office 365 and is considering between a single or multiple Office 365 tenants, I invite you to read this article.

If you or your customers are not ready to move entirely to the Cloud and Office 365, a hybrid scenario could be an interesting scenario and SharePoint 2019 RTM was recently announced with improved hybrid support! To learn all about SharePoint 2019 and all its features, click here.

If you want to know all about the latest SharePoint and Office 365 announcements from SharePoint Conference 2019, click here and here.

Happy SharePointing!

LEAVE A REPLY

Please enter your comment!
Please enter your name here