Introduction to Sequential Workflows
Creating a New Site Collection
Creating the Columns and Content Types
Creating the SharePoint Sequential Workflow in Visual Studio
Testing the Sequential Workflow
Conclusion
Additional Resources
Provided by: Justin Joyce, LANtek Computer Services
Contents
Create a site collection.
To create the new site collection
-
Open Central Administration and then click the Application Management link in the left navigation pane. The Application Management home page appears.
-
Under Site Collections, click Create Site Collections.
-
In the Create Site Collections page, ensure that the yellow box in the upper-right corner of the page (below the OK and Cancel buttons) displays the name of the new Web Application created in Step 1.
-
After selecting the correct Web Application, type a title. You may leave the description field blank if desired.
-
For Web Site Address, select a valid address and record it for later use in the Visual Studio 2010 project. An example of a valid address ishttp://servername:port/.
-
Under the Template Selection area, in the Select a template box, click the Publishing tab, and then select Publishing Portal. Figure 1 shows the Select a template box.
Figure 1. Choosing the site template
Although you can use other site template types, the publishing portal comes with the Workflow Tasks list already provisioned. If your instance of SharePoint does not have the Publishing Portal template available, you can use a Team Site template and provision the Workflow Tasks list.
-
Under Primary Site Collection Administrator, type the Active Directory account name of the primary site-collection administrator. If desired, also type a secondary site-collection administrator in the next box. Leave the Quota Template option set to No Quota.
-
Verify that all options are correct and then click OK.
Creating the SharePoint Sequential Workflow in Visual Studio.
To create the Workflow Tasks list
-
Return to the Site Actions menu and then click View All Site Content.
-
Click Create in the upper-left corner of the page and then locate the Tasks template, as seen in Figure 6.
Figure 6. Find the Tasks list template
-
Name the new list Workflow Tasks, and then click Create in the right column (see Figure 7).
Figure 7. Naming and creating the Workflow Tasks list
Creating the SharePoint Sequential Workflow in Visual Studio
Open Central Administration and then click the Application Management link in the left navigation pane. The Application Management home page appears.
Under Site Collections, click Create Site Collections.
In the Create Site Collections page, ensure that the yellow box in the upper-right corner of the page (below the OK and Cancel buttons) displays the name of the new Web Application created in Step 1.
After selecting the correct Web Application, type a title. You may leave the description field blank if desired.
For Web Site Address, select a valid address and record it for later use in the Visual Studio 2010 project. An example of a valid address ishttp://servername:port/.
Under the Template Selection area, in the Select a template box, click the Publishing tab, and then select Publishing Portal. Figure 1 shows the Select a template box.
Figure 1. Choosing the site template
Although you can use other site template types, the publishing portal comes with the Workflow Tasks list already provisioned. If your instance of SharePoint does not have the Publishing Portal template available, you can use a Team Site template and provision the Workflow Tasks list.
Under Primary Site Collection Administrator, type the Active Directory account name of the primary site-collection administrator. If desired, also type a secondary site-collection administrator in the next box. Leave the Quota Template option set to No Quota.
Verify that all options are correct and then click OK.
To create the Workflow Tasks list
-
Return to the Site Actions menu and then click View All Site Content.
-
Click Create in the upper-left corner of the page and then locate the Tasks template, as seen in Figure 6.
Figure 6. Find the Tasks list template
-
Name the new list Workflow Tasks, and then click Create in the right column (see Figure 7).
Figure 7. Naming and creating the Workflow Tasks list
Creating the SharePoint Sequential Workflow in Visual Studio
In the following steps, you create a sequential workflow project in Visual Studio 2010, and then add events and other properties to the workflow.
To create a SharePoint sequential workflow project
-
Start Visual Studio 2010. In the left column of the start page, click New Project.
-
In the Visual C# section of the Installed Templates tree, select SharePoint.
-
In the project type list, select Sequential Workflow.
-
Create a new directory for the solution and then name it CustomTaskApproval, as shown in Figure 8.
Figure 8. Creating a new SharePoint Sequential Workflow project
-
After the project is created, the SharePoint Customization Wizard is displayed. In the first page, use the URL of the site collection you created previously as the local site for debugging. Ensure that the solution is set to be deployed as a farm solution (see Figure 9), and then click Next.
Figure 9. Starting the SharePoint Customization Wizard
-
On the next page of the SharePoint Configuration Wizard, type the name of the workflow; in this case, use CustomTaskApproval – Workflow1as shown in Figure 10.
Figure 10. Choosing the workflow name and type
-
Select List Workflow as your template type and then click Next.
-
On the next page of the SharePoint Customization Wizard, Visual Studio 2010 automatically associates the workflow with the Requests list (see Figure 11). Leave the default values for the history and task lists.
Figure 11. Setting up the target list and task and history lists for the workflow
-
On the final configuration page, ensure that only the The workflow starts automatically when an item is created option is selected, as shown in Figure 12.
Figure 12. Selecting the workflow start options
-
With the workflow setup complete, begin adding the events and associated code.
Note By default, Visual Studio adds the onWorkflowActivated1 event to the design surface. This event is not used for this example; however, you can leave it on the design surface.
From the Toolbox, drag the following activities onto the design surface:
-
Code Name this activity InitializeItem. The Code activity is responsible for changes and checks of the item on its initial entry into the workflow.
-
CreateTask Name this activity createRequestTask. CreateTask is responsible for setting some of the properties on the initial creation of the task such as the description, to which person the task has been assigned, and so forth.
-
While This activity contains another activity that watches for the task to change. It is contingent upon a code condition (more on this later).
-
OnTaskChanged Name this activity onRequestTaskChanged. The OnTaskChanged activity is responsible for monitoring the task and ensuring any changes that the user makes to the task meet the validation rules—in this case, a description containing more than 100 characters in the item, and the custom approval field set correctly.
-
CompleteTask Name this activity completeRequestTask. Place this activity directly after the While activity. This activity is responsible for handling the actual completion of the task; that is, setting the built-in status field to Completed.
With all the activities in place, the design surface should now resemble Figure 13.
Figure 13. Workflow activities on the design surface
-
-
Next, create properties for the activities and binding correlation tokens. The properties need to be created in the code-behind first, as follows.
public Guid workflowId = default(System.Guid);
public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();// these properties are for the workflow task that will be created.
public SPWorkflowTaskProperties RequestTaskProperties = new SPWorkflowTaskProperties();
public SPWorkflowTaskProperties RequestTaskBeforeProperties = new SPWorkflowTaskProperties();
public Guid RequestApproveTaskId = default(Guid);
public int RequestApproveTaskItemId;
public bool RequestApproveComplete = false;
Then begin associating the correlation tokens with their corresponding activities by perform the following steps:
To associate the correlation tokens with their corresponding activities
-
For the onWorkflowActivated1 activity, create a new correlation token named workflowToken. Set the owner activity for this correlation token to Workflow1. In a larger scenario, this token would be used for many more activities and events on the design surface, but, for this exercise, it is used only on this activity. The task activities require their own correlation token to be shared between them to ensure that they are working on the same task.
-
For the createRequestTask, onRequestTaskChanged, and completeRequestTask activities, create a correlation token namedRequestTaskToken with an OwnerActivity of Workflow1. You can create this by typing it into the CorrelationToken box on the property pane for the first task event and then selecting it for the other activities.
Figure 14 shows what the properties pane for the createRequestTask activity looks like.
Figure 14. Setting the activity properties
-
Assign the correct public members from the code-behind to the ListItemId, TaskId, and TaskProperties fields by clicking the activity on the design surface and then selecting the property name from the Properties pane. Using the ellipses (…), select the member from the Bind to an existing member tab, and then click OK.
This will need to be done for each task activity on the design surface to ensure that they all have the same correlation token and the public members assigned correctly. The public members differ slightly for each of the task events. For example, onRequestTaskChanged adds aBeforeProperties attribute and completeRequestTask requires only TaskId (see Figure 15).
Figure 15. Binding the activity property to an existing member
Now that all correlation tokens and properties are set accordingly, you need to generate the associated methods.
To generate method signatures and add the code
-
Double-click each of the activities on the design surface. Visual Studio 2010 automatically displays the code and generates the method signature required for each activity. The exception to this is the While activity—you must create this method manually.
-
Create the associated method for the While activity by adding the following code.
private void notRequestTaskApproved(object sender, ConditionalEventArgs e)
{
e.Result = !RequestApproveComplete;
}In the properties pane for the While activity, set the Condition attribute to Code Condition and the Condition attribute contained under it tonotRequestTaskApproved, as shown in Figure 16. These settings cause the While activity to continue looping until the method returns the appropriate response.
Figure 16. Setting up the Code Condition property for the whileActivity
-
Next, add the following two helper methods.
private void ResestTask(SPListItem task, SPListItem currentItem, string message)
{
LogComment(message + currentItem.Title); // This line is very important. It keeps you from receiving
// the error "This task is currently locked by a running workflow."
task[SPBuiltInFieldId.WorkflowVersion] = 1;
task["Status"] = "In Progress";
task["Business Approval"] = "Undecided";
task.Update();
}private void LogComment(string logMessage)
{
SPWorkflow.CreateHistoryEvent(workflowProperties.Web, this.WorkflowInstanceId, 0, workflowProperties.Web.CurrentUser, new TimeSpan(), "Update", logMessage, string.Empty);
}The first helper method, ResetTask, is called only when a task needs to be reverted to an In Progress state, such as when a user attempts to complete it before filling in the required description field on the list item. This rollback method is required for the workflow solution to prevent theThis task is currently locked by a running workflow error that occurs when a task is rolled back to In Progress via code, if a user tries to change it again later. This error message is related to the workflow version on the task item; hence, explicitly setting the WorkflowVersion property to 1.
The second method is a simple logging function that enters updates to the Workflow History list.
-
With the setup of the workflow project in place, you can begin filling in the logic for the associated methods in the code behind file. Add the following code to the InitializeItem_ExecuteCode method:
private void InitializeItem_ExecuteCode(object sender, EventArgs e)
{
// Change the content type from Initial Request to simply Request. // This change makes Request Description a required field.
SPListItem currentItem = workflowProperties.Item; currentItem["ContentTypeId"] = workflowProperties.List.ContentTypes["Request"].Id;
currentItem.Update();
}When a request is entered, it is picked up by the workflow upon item creation. With the list set to allow users to enter requests with the content type of only Initial Request, the workflow can now change the content type of the item to Request. Changing the item to the Request type enables the Request Description field to display on the edit form as a required field.
-
Next, add the following code to the createRequestTask_MethodInvoking method. This is where you set up all the applicable properties for the workflow task.
private void createRequestTask_MethodInvoking(object sender, EventArgs e)
{
// Now create the approval task.
SPListItem currentItem = workflowProperties.Item; // Set up some of the properties.
RequestApproveTaskId = Guid.NewGuid();
RequestTaskProperties.Title = workflowProperties.Item["Title"].ToString() + " is ready for review";
RequestTaskProperties.Description = "Please review the request and ensure it is valid. If it is valid, then please select 'I Approve' on this task and save it.";
LogComment("Request Task Created.");
} -
Finally, add the following code into the onRequestTaskChanged_Invoked method.
private void onRequestTaskChanged_Invoked(object sender, ExternalDataEventArgs e)
{
int tid = onRequestTaskChanged.AfterProperties.TaskItemId;
SPListItem task = workflowProperties.Web.Lists["Workflow Tasks"] .GetItemById(RequestApproveTaskItemId); SPListItem currentItem = workflowProperties.Item; try
{
// Ensure the field exists on the item.
if (task["Business Approval"] != null && currentItem["Request Description"] != null)
{
// Evaluate the value of the field.
if (task["Business Approval"].ToString() == "I Approve" || task["Business Approval"].ToString() == "I Do NOT Approve")
{
if (currentItem["Request Description"].ToString().Length >= 100)
{
RequestApproveComplete = true;
}
else
{
RequestApproveComplete = false;
ResestTask(task, currentItem, "Request Description is not long enough.");
}
}
else
{
RequestApproveComplete = false;
ResestTask(task, currentItem, "Business Approval is not set.");
}
}
else
{
// This should never happen because there is a default, but always good just in case.
RequestApproveComplete = false;
ResestTask(task, currentItem, "Business Approval status is null or no Request Description.");
}
}
catch (Exception ex)
{
RequestApproveComplete = false;
ResestTask(task, currentItem, "Exception.");
LogComment(ex.ToString());
}
}This method evaluates the Request item, ensures that the Request Description field is properly filled in, and that the associated workflow task has been marked with the correct status code. If all criteria are met, RequestApproveComplete returns True, causing the While activity to exit.
-
Finally, add the following code to the completeRequestTaskApproved activity.
private void completeRequestTask_MethodInvoking(object sender, EventArgs e)
{
// Grab the task item so the workflow can complete it.
SPListItem task = workflowProperties.Web.Lists["Workflow Tasks"] .GetItemById(RequestApproveTaskItemId); // This line is very important. It keeps you from receiving
// the error "This task is currently locked by a running workflow."
task[SPBuiltInFieldId.WorkflowVersion] = 1;
task["Status"] = "Completed";
task.SystemUpdate(false); SPListItem currentItem = workflowProperties.Item;
if (task["Business Approval"].ToString() == "I Do NOT Approve")
{
string currentTitle = workflowProperties.Item["Title"].ToString();
workflowProperties.Item["Title"] = "DECLINED: " + currentTitle;
workflowProperties.Item.Update();
}
else
{
string currentTitle = workflowProperties.Item["Title"].ToString();
workflowProperties.Item["Title"] = "APPROVED: " + currentTitle;
workflowProperties.Item.Update();
}
}Again, you are setting the workflow version to keep the task from being locked when the update is performed from the code. The workflow sets the built-in Status field to Completed, which ends the task. A quick evaluation is then performed on the state of the task (approved or declined), and the item is updated accordingly to reflect the decision.
The final step in this process is the configuration of the custom Business Approval field on the Workflow Task content type.
To perform the final site configuration for the custom task approval field
-
Before you are able to edit the fields associated with the Workflow Task, it needs to be added to the Workflow Tasks list. On the Debug menu in Visual Studio 2010, click Start Debugging or press F5, as shown in Figure 17. This launches a new browser window and attaches the debugger to the w3wp process.
Figure 17. Starting the workflow in debug mode
-
When the site is loaded, go to the requests list and create an item. This causes the Workflow Task content type to be automatically added to theWorkflow Tasks list. To verify this, on the Site Actions menu, click View All Site Content. Select the Workflow Tasks list, and then click List Settings.
On the List Settings page, you see the Workflow Task content type in the list of content types, as shown in Figure 18.
Figure 18. Viewing the content types on the Workflow Tasks list
-
Click the Task content type and use the Delete this content type option to remove it from the Workflow Tasks list. Repeat this procedure with the Summary Task content type.
-
Now, click the Workflow Task content type to go to the settings page.
-
Click the Status field, and then change its Column Settings from Optional to Hidden. Click OK to save the changes.
-
On the settings page for the Workflow Task content type, under the Columns section, click Add from existing site or list columns.
-
Locate the Business Approval column in the list and then double-click it to move it to the Columns to add list (see Figure 19). Click OK to save the changes.
Figure 19. Adding custom columns to the Workflow Task content type
Testing the Sequential Workflow
In this section, you test the workflow. You do this by creating a request and then updating the request to see the results.
To create a request
-
In the Requests list, click the Add new item link in the lower-left corner of the list view. The New Item dialog box appears, as shown in Figure 20.
Figure 20. New item page for the requests list
-
Type a title for the request and click Save.
-
The associated task is created by the workflow in the Workflow Tasks list. To view the task, in the Site Actions menu, click View All Site Content, and then select the Workflow Tasks list under the Lists heading. The task appears at the top of the main view, as pictured in Figure 21.
Figure 21. List view of the newly created task
-
Click the title of the task to display the full task form. Click Edit in the top-left corner of the form to place the task in edit mode (see Figure 22).
Figure 22. Workflow Task edit form with custom approval field
Clicking Save with the Undecided value still in the Business Approval field causes the built-in Status field to be set to In Progress and logs the following into the workflow history (see Figure 23).
Figure 23. Viewing the Workflow History list
Likewise, if you omit the Request Description field on the list item while trying to approve or decline the task, the Status field is set to In Progress.
-
Now, go back to your Request item and edit it. You see that the Request Description field is now showing as required. Type a value of more than 100 characters (see Figure 24) and save your changes. You can then approve or decline the task.
Figure 24. Request list item edit form
-
Now that the Request item is properly filled in, go back to the Workflow Task list, edit the task associated to the Request item, and then select I Do NOT Approve in the Business Approval field. This action causes the workflow to set the Status field to Completed, as seen in Figure 25.
Figure 25. View of the completed (and rejected) task in the Workflow Task list
You can see the change in the title for the Request item in Figure 26
Figure 26. Title change performed by the workflow on a rejected task
If the workflow task is approved, the title of the Request item is altered to reflect the approval action (see Figure 27)
Figure 27. Title change performed by the workflow on an approved task