Building an Expense Report Approval Workflow for SharePoint Server 2007 Using Visual Studio 2008

Summary:  Learn how to create a sequential workflow for Microsoft Office SharePoint Server 2007 to manage an expense report approval process.

Office Visual How To

Applies to:  2007 Microsoft Office System, Microsoft Office SharePoint Server 2007, Microsoft Visual Studio 2008

Mike Rand, 3Sharp

June 2008

Overview

Microsoft Visual Studio 2008 provides built-in templates to create powerful Microsoft Office SharePoint Server 2007 workflows right out of the box. In this Microsoft Office Visual How To, you create a sequential workflow to manage an expense report approval process. You will use the Microsoft Office InfoPath 2007 Expense Report form in a modified form. Your form will include fields for VP Name and E-mail. To learn how you can modify this form, see Creating a Custom Approval Workflow for SharePoint Server 2007 Using SharePoint Designer 2007

See It Building an Expense Report Approval Workflow

Watch the Video

Video Length: 00:06:33

File Size: 21.2 MB WMV

Code It | Read It | Explore It

Code It

The scenario that this Visual How To covers is one where an expense report is submitted and must be approved. If the expense report is less than $5,000.00, a manager is required to approve it. If the expense report is equal to, or more than, $5,000.00, a vice-president (VP) is required to approve the expense report.

The following sections show you how to create a Sequential Workflow project in Visual Studio 2008, create a task form that can be used by a workflow, lay out a workflow, and add code to handle the business logic. It also covers running the project from Visual Studio 2008.

Creating a Visual Studio 2008 Sequential Workflow project

First, you create a Visual Studio project to build your workflow.

To create a Visual Studio 2008 Sequential Workflow project

  1. Start Visual Studio 2008.

  2. On the File menu, point to New, and then click Project.

  3. Under the Office Project Type, select the SharePoint 2007 Sequential Workflow project template.

  4. Type ExpenseReportWF in the name text box, and then click OK.

  5. Type a valid SharePoint Web URL (this scenario uses http://moss.litwareinc.com/expense). Click Next.

  6. Select a library or list to associate with your workflow. Click Next.

  7. Leave the default options for how a workflow can be started, Manually by users and When an Item is created. Click Finish.

  8. Now, rename the SequentialWorkflowActivity from the default workflow1.cs to ExpenseReportWorkflow.

  9. Also rename the OnActivatedWorkflowActivity activity from the default onWorkFlowActivated1 to onExpenseWorkflowActivated.

Creating the Approval Task Form with InfoPath 2007 Designer

Next, you create the custom approval task form.

To create the approval form

  1. Start Microsoft Office InfoPath 2007.

  2. On the File menu, select Design a Form Template.

  3. Select a blank form, and make sure that the Enable browser compatible features only check box is selected. Click OK.

  4. In the Design Tasks task pane, select Layout.

  5. Drag a Table with Title item onto the form. Type an appropriate Title.

  6. Next, select a , drag it into the table that you just created.

  7. In the table dialog box, select 2 columns and 3 rows. Click OK.

  8. Merge the first row's columns, and add text to describe the purpose of the form.

  9. Click the Design Tasks link in the Layout task pane to return to the main task pane.

  10. In the Design Tasks task pane, select Controls.

  11. Drag an Option Button control into the first column of the second row.

  12. Set the number of options to two. Click OK.

  13. Type Approve for the first option.

  14. Type Reject for the second option.

  15. Right-click one of the Option Buttons, select Option Button Properties, and change the field name to optApproved. Click OK.

  16. Drag a button into the first column of the third row.

  17. Select and right-click the button. Select Button Properties. Rename the button to Submit.

  18. Click Rules to add new rules for this button, and then click Add.

  19. Click Add Action. In the Action drop-down list, select Submit using a data connection.

  20. Click Add. This starts the Data Connection Wizard.

  21. Select Create a new connection to, and then select Submit data. Click Next.

  22. Select the option To the hosting environment. Click Next, and then click Finish.

  23. Repeat steps 18 through 22, but this time, add a rule to close the form when it is submitted.

  24. On the menu, select Tools, and then select Form Options.

  25. In the Form Options dialog box, select Security and Trust.

  26. Clear the Automatically determine security level check box.

  27. Select Domain, and then click OK.

  28. On the File menu, select Publish.

  29. In the Save As dialog box, save the template to a working directory and name it ExpenseApprovalForm.xsn (do not save in the Visual Studio solution directory; you will publish to that directory next).

  30. When the publishing wizard starts,you are asked where you want to publish the form. Select To a network location, and then click Next.

  31. Browse to the Visual Studio project directory that you created earlier.

  32. Name the template ExpenseApprovalForm, and click Next.

  33. Clear the text box. You do not want users to have access to this form outside your workflow. Click Next.

  34. Click OK on the warning box.

  35. Click Publish.

  36. Click Close, and close InfoPath.

Laying Out a Sequential Workflow

Now you need to set up your workflow. You can start by laying out the workflow in the Designer and then updating all required properties. Later, you add the code to drive the workflow.

To lay out a sequential workflow

  1. Open the Visual Studio 2008 project you created earlier.

  2. Open the Toolbox. Expand the SharePoint Workflow controls and the Windows Workflow v3.0 controls.

  3. Drag an IfElse activity onto the designer, directly below the onExpenseWorkflowActivated activity.

    Note

    Do not drop this activity before the onExpenseWorkflowActivated activity; although the designer allows you to do this, the workflow will fail in SharePoint Server.

  4. Rename the first branch of the IfElse activity to IfElseLessThan5K.

  5. Rename the second branch to IfElseMoreThan5K.

  6. Next, drag a CreateTask activity to the first IfElse branch. Rename it to createTaskMngrApproval.

  7. Next, drag a While activity and drop it below the createTaskMngrApproval activity. Rename this to whileActivityMngr.

  8. Drag an OnTaskChanged activity, and drop it inside the While activity that you just created. Rename it to onTaskChangedMngr.

  9. Drag a CompleteTask activity and drop it after the While activity. Rename this to completeTaskMngrApproval.

  10. Repeat steps 6 through 9 for the second IfElse branch, and replace the term Mngr or Manager with VP.

    Note

    You may see red circles with exclamation points indicating there are problems with your workflow. You handle these in the next section.

    Workflow layout

    Figure 1. Locating default.master

Updating the Properties in Your Workflow

You must set some properties before you can move on to enable the workflow engine to process your workflow properly. You will set properties such as the CorrelationToken, which the workflow engine uses to uniquely identify a task, Task Id, Task Properties, and event handlers to provide custom logic. You will start at the top of your workflow and work your way down.

To update properties in the activities on your workflow

  1. Make sure the properties window is open, and select the onExpenseWorkflowActivated activity.

  2. Right-click and select Generate Handlers.

    The code-behind class opens, and you see an autogenerated method stub. Switch back to the Designer.

  3. Select the first IfElse branch, IfElseLessThan5K.

  4. Select the Condition property, and in the drop-down list, select Code Condition .

  5. Expand the Condition property. You will notice that there is another sub-property named Condition. Select this property, and type IsReportTotalLessThan5K. Press ENTER.

  6. The code-behind class opens, and you will see an autogenerated method stub IsReportTotalLessThan5K. Switch back to the Designer.

  7. Next, select the createTaskMngrApproval activity.

  8. Go to the CorrelationToken property, and type mngrTaskToken.

    Note

    It is important to point out that the Correlation Token for the workflow should not be used here. Each Task should use its own Correlation Token.

  9. Expand the CorrelationToken property, and in the OwnerActivityName property, select ifElseLessThan5K in the drop-down list.

  10. Select the TaskId property, and then click the ellipsis (…) button.

  11. Select the Bind to a new member tab.

  12. Type the following member name: taskId_Mngr.

  13. Select the Create Field option button, and then click OK.

  14. Right-click the createTaskMngrApproval activity, and then select Generate Handlers.

    The code-behind class opens, and you should see an autogenerated method stub. Switch back to the Designer.

  15. Repeat this process for the TaskProperties property.

  16. Select the whileActivityMngr activity.

  17. Select the Condition Property, and in the drop-down list, select Code Condition.

  18. Expand the Condition property. Again, you will see a sub-property named Condition. Select this property and type the following text: notFinishedMngr. Press ENTER.

  19. Again, the code behind class opens, and you will see an autogenerated method stub notFinishedMngr. Switch back to the Designer.

  20. Select the onTaskChangedMngr activity.

  21. Select the CorrelationToken property, and then in the drop-down list, select mngrTaskToken.

  22. Select the TaskId property, and then click the ellipsis (…) button.

  23. Select the Bind to an existing member tab.

  24. Select the taskId_Mngr property, and then click OK.

  25. Right-click the onTaskChangedMngr activity, and then select Generate Handlers. This generates the method stub as you saw previously from the properties window. Switch back to the Designer.

  26. Next, set up your BeforeProperties and AfterProperties. To set these up, click the ellipsis (…) button, select to Bind to a New Member. Select create field, and give them the following names: beforeProperties_Mngr, afterProperties_Mngr.

  27. Select the completeTaskMngrApproval, and repeat the same steps you just did for the onTaskChangedMngr activity.

  28. Now repeat these steps for the second IfElse brand, ifElseMoreThan5K. Replace the term Manger or mngr with VP.

Adding Code to the Workflow

Now that you have designed the workflow, you must add code to provide the logic.

Add code to the workflow

  1. Open the workflow1.cs class.

  2. Add properties for the following private fields:

    • bool isFinishedMngr

    • bool isFinishedVP

    • string employeeName

    • string mngrEmail

    • string vpEmail

    • double reportTotal

  3. Next, add a property named EmailBody, and add the following code.

    get
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.Append("An expense report submitted by {0} in the amount of ${1}  
          has been submitted to http://moss.litwareinc.com/expense. ");
        sb.Append("Please navigate to this document library and 
          either approve or reject this expense report. ");
        sb.Append("<br /><br />");
        sb.Append("Regards,");
        sb.Append("<br />");
        sb.Append("Litware Administrator");
    
        return String.Format(sb.ToString(), EmployeeName, ReportTotal.ToString());
    }
    
  4. Add another property named EmailSubject, and return the following string: Expense Report Ready for Review.

  5. Go to the onWorkflowActivated1_Invoked method, and add the following code.

    workflowId = workflowProperties.WorkflowId;
    
    // Set promoted column values.
    employeeName = workflowProperties.Item["Employee Name"].ToString();
    mngrEmail = workflowProperties.Item["Manager Email Address"].ToString();
    vpEmail = workflowProperties.Item["VP Email Address"].ToString();
    reportTotal = (double)this.workflowProperties.Item["Report Total"];
    
  6. Now, you can handle the code for the Manager side of your workflow. Go to the createTaskMngrApproval_MethodInvoking method, and add the following code.

    taskId_Mngr = Guid.NewGuid();
    taskProperties_Mngr.TaskType = 1;
    taskProperties_Mngr.Title = "Expense Report Approval - Manager";
    taskProperties_Mngr.StartDate = DateTime.Today;
    taskProperties_Mngr.AssignedTo = workflowProperties.Item["Domain"].ToString() 
      + "\\" + workflowProperties.Item["Manager Name"].ToString(); 
    taskProperties_Mngr.PercentComplete = 0.0f;
    
    taskProperties_Mngr.Description = "Expense Report";
    taskProperties_Mngr.EmailBody = this.EmailBody;
    taskProperties_Mngr.HasCustomEmailBody = true;
    taskProperties_Mngr.SendEmailNotification = true;
    

    Note

    In the preceding example, I retrieve the Domain field from the expense report form; this was a modification to the original form and was added for this scenario.

  7. Go to the notFinishedMngr method, and add the following code.

    e.Result = !isFinishedMngr;
    
  8. Go to the onTaskChangedMngr_Invoked method, and add the following code.

    string selVal = afterProperties_Mngr.ExtendedProperties["optApproved"].ToString();
    int val = 0;
    if (!String.IsNullOrEmpty(selVal))
    {
        if (Int32.TryParse(selVal, out val))
        { 
            if (val == 1 || val == 2)
            {
                isFinishedMngr = true;
            }
        }
    }
    
  9. Go to the completeTaskMngrApproval_MethodInvoking method, and add the following code.

    taskProperties_Mngr.PercentComplete = 100; 
    
  10. Repeat the previous steps for the VP side or your workflow.

  11. Now, you need to add the business logic. Go to the IsReportTotalLessThan5K method, and add the following code.

    if (ReportTotal < 5000)
    {
        e.Result = true;
    } 
    
  12. Go to the IsReportMoreThan5K method, and add the following code.

    if (ReportTotal >= 5000)
    {
        e.Result = true;
    }
    

Updating the Workflow.xml File

Next, you must make sure that your Workflow.xml file is updated to include your Expense Report Approval task form.

To update Workflow.xml

  1. Add the following element as a child to the MetaData element.

    <Task1_FormURN>urn:schemas-microsoft-com:
      office:infopath:ExpenseReportApprovalForm:-myXSD-2008-04-09T15-47-41</Task1_FormURN>
    
  2. Add the TaskListContentTypeId attribute to the Workflow element.

    TaskListContentTypeId="0x01080100C9C9515DE4E24001905074F980F93160"
    

Updating the Feature.xml File

Next, you must make sure that the Feature.xml file is updated to include your Expense Report Approval task form.

To update Feature.xml

  • Add the following element as a child to the ElementManifests element.

    <ElementFile Location="ExpenseReportApprovalForm.xsn" />
    

Running the Workflow Project from Visual Studio 2008

All that's left to do now is to press F5 and run the project. Visual Studio 2008 lets you debug your workflows by placing break points in code. Visual Studio 2008 also handles the details of deploying your workflow to SharePoint Server. You may still need to add the workflow to your Document Library manually in SharePoint Server.

Read It

Visual Studio provides a great platform to create and debug workflows. As you can see, building a simple sequential workflow to generate an expense report approval process in Visual Studio can be as easy as dragging and dropping. However, by adding custom code to your workflow, you can generate very powerful and robust workflows. A benefit of creating workflows from Visual Studio is that you can package the solutions and also deploy them. For more information about how to do this, see Configuring and Deploying Workflows to SharePoint Server 2007 Using Solution Packages.

Explore It