Creating Multiple Tasks from a SharePoint 2010 Workflow

SharePoint Visual How To

Summary:  Learn how to create multiple Microsoft SharePoint 2010 tasks in a Microsoft Visual Studio 2010 workflow project.

Applies to: SharePoint Foundation 2010 | SharePoint Server 2010 | Visual Studio | Visual Studio 2008 | Visual Studio 2010

Provided by:  Scot Hillier, Microsoft SharePoint MVP

Overview

A task is a key component of any Microsoft SharePoint 2010 workflow. Your workflow might need to assign and track multiple tasks. You can create multiple SharePoint tasks from a Microsoft Visual Studio 2010 workflow project.

Code It

To create multiple tasks in a workflow, you must first create a custom activity that encapsulates a single task. Then you use a ReplicatorActivity activity in the workflow to create multiple tasks.

Creating a Custom Activity

Begin by creating a custom activity that inherits from the SequenceActivity class. This custom activity has the standard CreateTask activity, onTaskChanged activity, and CompleteTask activity, as shown in Figure 1.

Figure 1. Custom activity

Custom activity
namespace MultipleTasks
{
    public partial class SPTaskActivity : SequenceActivity
    {
        public SPTaskActivity()
        {
            InitializeComponent();
        }

        public Guid SPTaskId = default(System.Guid);
        public Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties 
          SPTaskProperties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public string TaskTitle { get; set; }
        public string TaskDescription { get; set; }
        public string TaskAssignedTo { get; set; }
        public DateTime TaskDueDate { get; set; }
        private bool complete;
        public Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties 
          SPAfterProperties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties 
          SPBeforeProperties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public Guid TaskStatusFieldId = 
          new Guid("c15b34c3-ce7d-490a-b133-3f4de8801b76");

        private void createSPTask_MethodInvoking(object sender, 
          EventArgs e)
        {
            // Create task.
            SPTaskId = Guid.NewGuid();
            SPTaskProperties.Title = TaskTitle;
            SPTaskProperties.Description = TaskDescription;
            SPTaskProperties.AssignedTo = TaskAssignedTo;
            SPTaskProperties.PercentComplete = 0;
            SPTaskProperties.StartDate = DateTime.Today;
            SPTaskProperties.DueDate = TaskDueDate;
        }

        private void notComplete(object sender, 
          ConditionalEventArgs e)
        {
            e.Result = !complete;
        }

        private void onSPTaskChanged_Invoked(object sender, 
          ExternalDataEventArgs e)
        {
            string taskStatus = 
              SPAfterProperties.ExtendedProperties[TaskStatusFieldId].ToString();
            if (taskStatus.Equals("Completed"))
                complete = true;
        }

        private void completeSPTask_MethodInvoking(object sender, 
          EventArgs e)
        {
            SPTaskOutcome = "Task Complete";
        }

        public String SPTaskOutcome = default(System.String);
    }
}

Creating the Workflow

Use the custom activity that you created in a workflow with a ReplicatorActivity activity to create multiple tasks in the same workflow. Figure 2 shows a sequential workflow that includes the ReplicatorActivity activity.

Figure 2. Sequential workflow

Sequential workflow
namespace MultipleTasks
{
    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }

        public Guid workflowId = default(System.Guid);
        public SPWorkflowActivationProperties workflowProperties = 
          new SPWorkflowActivationProperties();
        public IList assignees = default(System.Collections.IList);

        private void onWorkflowActivated1_Invoked(object sender, 
          ExternalDataEventArgs e)
        {
            workflowId = workflowProperties.WorkflowId;
        }

        private void replicateTasks_Initialized(object sender, 
          EventArgs e)
        {
            // Create a set of assignees for task.
            assignees = new ArrayList();
            string[] uids = 
              workflowProperties.Item["Additional Reviews"].ToString().Split(';','#');
            for (int i = 0; i < uids.Length; i += 4)
                assignees.Add(workflowProperties.Web.SiteUsers.GetByID
                  (int.Parse(uids[i])).LoginName);

            // Set data for first task.
            SPUser employee = 
              GetUserFromPickerString(workflowProperties.Item["Employee"].ToString());
            spTaskActivity1.TaskAssignedTo = 
              assignees[assignees.Count - 1].ToString();
            spTaskActivity1.TaskTitle = "Vacation Request Approval";
            spTaskActivity1.TaskDescription = 
              "Approve Vacation Request for " + employee.Name;
            spTaskActivity1.TaskDueDate = DateTime.Today.AddDays(7);
        }

        private void replicateTasks_ChildInitialized(object sender, 
          ReplicatorChildEventArgs e)
        {
            // Loop through each assignee.
            SPUser employee = 
              GetUserFromPickerString(workflowProperties.Item["Employee"].ToString());
            spTaskActivity1.TaskAssignedTo = e.InstanceData.ToString();
            spTaskActivity1.TaskTitle = "Vacation Request Approval";
            sp TaskActivity1.TaskDescription = 
              "Approve Vacation Request for " + employee.Name;
            spTaskActivity1.TaskDueDate = DateTime.Today.AddDays(7);
        }

        private SPUser GetUserFromPickerString(string PickerString)
        {
            string id = string.Empty;
            try
            {
                id = PickerString.Substring(0, PickerString.IndexOf(';'));
                return workflowProperties.Web.SiteUsers.GetByID(int.Parse(id));
            }
            catch { return null; }
        }
    }
}
Read It

When you create multiple tasks in a SharePoint workflow, you must first create a custom activity that encapsulates creating and managing a single task. Then you use the activity in the workflow.

Custom Activities

You can create custom activities directly in the workflow project in which you intend to use them. In this example, you create the custom activity by inheriting from the SequenceActivity class. When you inherit from the SequenceActivity class, you can then use the designer to add other activities to your custom activity.

Following is a review of the activities:

  • The CreateTask activity creates a new task in a SharePoint list.

  • The OnTaskChanged activity checks whether the task is complete each time a user changes the task in some way.

  • The CompleteTask activity finishes the task and allows the workflow to continue.

Using the ReplicatorActivity Activity

After the custom activity is complete, you can use it in a workflow. The workflow uses the ReplicatorActivity activity to create multiple tasks through the custom activity. The ReplicatorActivity activity is initialized by using a set of users. The underlying custom activity is called one time for each user in the set, and a task is assigned.

See It

Watch the video

> [!VIDEO https://www.microsoft.com/en-us/videoplayer/embed/ba6e1c63-2ec5-4ad8-95f7-942de5982fa1]

Length: 00:08:49

Explore It

About the Author

Scot Hillier is an independent consultant and Microsoft SharePoint Most Valuable Professional (MVP) focused on creating solutions for Information Workers with SharePoint, Office, and related .NET Framework technologies. He is the author/coauthor of 15 books and DVDs on Microsoft technologies, including Inside Microsoft SharePoint 2010 and Professional Business Connectivity Services. Scot splits his time between consulting on SharePoint projects, speaking at SharePoint events like Tech-Ed, and delivering training for SharePoint developers. Scot is a former U.S. Navy submarine officer and graduate of the Virginia Military Institute. Scot can be reached at scot@shillier.com.