Building a MOSS Workflow with Visual Studio 2008 and InfoPath
Visual Studio 2008 offers a somewhat better environment for creating SharePoint workflows. Creating, debugging, and deployment are all simpler, but not yet where we would like them to be. In this article, I'll show you how to create a complete workflow for automating the employee performance review process. You will create InfoPath forms, a workflow assembly, and a feature. The article will walk you through everything you need to create MOSS workflows using InfoPath and Visual Studio 2008.
Prerequisites
Before beginning this exercise, you must have access to a MOSS installation. In the MOSS farm, create a Team Site named “Reviews”. In the Team Site, add a Contacts list named “Employees” and a Task list named “Review Tasks”. Additionally, make sure that this site has the Standard and Enterprise Features of MOSS enabled because these are required for InfoPath form support.
Creating the InfoPath Workflow Forms
Before you can start creating the workflow in Visual Studio, you need to create the InfoPath forms that will support the workflow in SharePoint. A SharePoint workflow requires three separate InfoPath forms: the association form, the initiation form, and the task form. The association form is displayed to the user when the workflow is first associated with a list. The initiation form is displayed to the user when the workflow is launched. The task form is displayed when a user completes an assigned task. Over the next few sections, you will create all three of these forms.
Creating the Workflow Association Form
The association form allows users to specify key information when a workflow is first associated with a list. In this exercise, you will specify information about the manager who will be performing the performance reviews. The assumption here is that you will create separate lists for each manager that will use the workflow.
Creating the Data Schema for the Form
The data schema for the form will support selecting the name of the manager to associate with the review as well as the type of review and comments.
1. Start Microsoft InfoPath.
2. In the Getting Started dialog, click the link titled Design a Form Template.
3. Check the box titled “Enable Browser-Compatible Features Only”.
4. In the Design a Form Template dialog, select a Blank template and click the OK button to start with a blank form.
5. When the blank form opens, click the Data Source link in the Design Tasks pane.
6. Right-click the myFields node and select Add.
7. In the Add Field or Group dialog, type ManagerGroup in the Name field
8. Change the type to Group and click the OK button.
9. Right-click the managerGroup node and select Add.
10. In the Add Field or Group dialog, type Person in the Name field
11. Change the type to Group and check the Repeating box.
12. Click the OK button.
13. Right-click the manager node and select Add.
14. In the Add Field or Group dialog, type DisplayName in the Name field and press the OK button.
15. Right-click the manager node and select Add.
16. In the Add Field or Group dialog, type AccountId in the Name field and press the OK button.
17. Right-click the manager node and select Add.
18. In the Add Field or Group dialog, type AccountType in the Name field and press the OK button.
19. Right-click the myFields node and select Add.
20. In the Add Field or Group dialog, type ReviewType in the Name field and press the OK button.
21. Right-click the myFields node and select Add.
22. In the Add Field or Group dialog, type ReviewComments in the Name field and press the OK button.
Creating the Contact Selector Data Source
The Contact Selector data source will allow the form to present a list of possible managers based on the user in SharePoint.
1. Open Notepad and type the following code replacing the URL with one that refers to your SharePoint server.
<Context siteUrl=http://moss />
2. Save the file to a temporary working directory as Context.xml
3. In the Design Tasks pane, click the Data Source link.
4. Click the Manage Data Connections link.
5. In the Data Connections dialog, click the Add button.
6. In the data connection wizard, select to create a connection to receive data.
7. Click the Next button.
8. On the next screen of the wizard, select the XML Document option and click the Next button.
9. Click the Browse button.
10. In the Open dialog, locate the Context.xml file, select it, and click the Open button.
11. Click the Next button.
12. On the next screen of the wizard, ensure that the option labeled Include the Data Source as a Resource File in the Form Template or Template Part is selected.
13. Click the Next button.
14. On the next screen, ensure the box labeled Automatically Retrieve Data When Form Is Opened is checked and that the connection is named Context. Then click the Finish button.
15. In the Data Connections dialog, click the Close button.
Laying Out the Form
1. Click on the Design Tasks link at the top of the Data Source pane.
2. Click the Layout link in the Design Tasks pane.
3. Drag the Custom Table layout onto the blank form.
4. In the Insert table dialog, enter 2 in the Columns field and 2 in the Rows field, and click the OK button.
5. Click the Design Tasks link at the top of the Layout pane.
6. Click the Controls link in the Design Tasks pane.
7. Uncheck the box labeled Automatically Create Data Source.
8. Click the link titled Add or Remove Custom Controls.
9. Click the Add button.
10. In the Add Custom Control Wizard, select the ActiveX Control option and click the Next button.
11. Select the Contact Selector control from the list and click the Next button.
12. Select the option titled Don’t Include a CAB file and click the Next button.
13. Select the option titled Value and click the Next button.
14. Select the drop-down titled Field or Group (Any Type) and click the Finish button.
15. Click the Close button.
16. Click the OK button.
17. Drag a Contact Selector from the Controls pane and drop it in the top right cell of the table.
18. In the Binding dialog, select the ManagerGroup field and click the OK button.
19. Use plain text to label the Contact Selector as Manager.
20. Drag a button from the Controls pane and drop it in the bottom right cell of the table.
21. Right-click the button and select Button Properties from the context menu.
22. Enter Done in the Label field.
23. Click the Rules button.
24. In the Rules dialog, click the Add button.
25. In the Rules dialog, click the Add Action button.
26. In the Action dialog, select Submit Using a Data Connection.
27. Click the Add button.
28. In the data connection wizard, select to create a new connection to submit data and click the Next button.
29. On the next screen select the option to submit the data to The Hosting Environment. This will ensure that the contents of the form are submitted back to the SharePoint workflow process.
30. Click the Next button.
31. Click the Finish button.
32. In the Action dialog, click the OK button.
33. In the Rules dialog, click the Add Action button.
34. Select Close the Form.
35. Click the OK button.
36. In the Rule dialog, click the OK button.
37. In the Rules dialog, click the OK button.
38. In the Button Properties dialog, click the OK button.
46. Save the form to a temporary working directory as AssocForm.xsn. Figure 1 shows the completed form.
Note: You can test the Contact Selector control by previewing the InfoPath form
Figure 1. The workflow association form
Creating the Workflow Initiation Form
The initiation form allows users to specify key information when a workflow instance is first started. In this exercise, you will specify information about the type of performance review and add any relevant comments. Because the initiation form uses the same data source as the association form, you’ll create the initiation form by modifying the association form.
1. Open AssocForm.xsn in Design mode in InfoPath 2007 if it is not already open.
2. Select File >>Save As from the main menu.
3. In the Save As dialog, change the form name to InitForm.xsn and click the Save button. This ensures that the data elements and namespace for the initiation form exactly match those of the association form. This allows the forms to share data values.
4. Remove the Contact Selector control. Do not delete the button.
5. Right click the layout table and select Insert>>Rows Below from the context menu.
6. Click the Design Tasks link at the top of the task pane.
7. Click the Controls link in the Design Tasks pane.
8. Uncheck the box labeled Automatically Create Data Source.
9. Drag a Drop-Down List Box from the Controls pane and drop it in the top right left of the table.
10. In the Binding dialog, select the ReviewType node and click the OK button.
11. Right click the Drop-Down List and select Properties from the context menu.
12. In the Data Tab, click the Add button
13. Add a new Choice by entering Annual in both the Value and Display Name fields. Repeat this to add choices for Performance, Promotion, and Special.
14. When you are done, click the OK button.
15. Drag a text box from the Controls pane and drop it in the middle right cell of the table.
16. In the Text Box Binding dialog, select the ReviewComments field and click the OK button.
17. Dress up the form by adding text labels to the fields and making the comments text multi-line.
18. Save the initiation form and close InfoPath. Figure 2 shows the completed form.
Figure 2. The workflow initiation form
Creating the Task Form
The task form is presented to the user when he or she has a task to perform in the workflow. In this exercise, the form is simply used to record the completion of the task. In more complicated workflows, the form could support different views for different user roles along with supporting fields.
1. Start Microsoft InfoPath.
2. In the Getting Started dialog, click the link titled Design a Form Template.
3. Check the box titled Enabled Browser-Compatible Features only
4. In the Design a Form Template dialog, select a Blank template and click the OK button.
5. When the blank form opens, click the Data Source link in the Design Tasks pane.
6. Right-click the myFields node and select Add.
7. In the Add Field or Group dialog, type ReviewCompleted in the Name field.
8. Select True/False (Boolean) from the Data Type drop-down list and click the OK button.
9. Right-click the myFields node and select Add.
10. In the Add Field or Group dialog, type ReviewNotes in the Name field and press the OK button.
11. Click the Design Tasks link at the top of the Data Source pane.
12. Click the Layout link in the Design Tasks pane.
13. Drag the Custom Table layout onto the blank form.
14. In the Insert Table dialog, enter 1 in the Columns field and 3 in the Rows field, and click the OK button.
15. Click the Design Tasks link at the top of the Layout pane.
16. Click the Controls link in the Design Tasks pane.
17. Uncheck the box labeled Automatically Create Data Source.
18. Drag a check box from the Controls pane and drop it in the top cell of the table.
19. In the Check Box Binding dialog, select the ReviewCompleted field and click the OK button.
20. Drag a text box from the Controls pane and drop it in the bottom cell of the table.
21. In the Text Box Binding dialog, select the ReviewNotes field and click the OK button.
22. Drag a button from the Controls pane and drop it in the bottom cell.
23. Right-click the button and select Button Properties from the context menu.
24. Enter Done in the Label field.
25. Click the Rules button.
26. In the Rules dialog, click the Add button.
27. In the Rules dialog, click the Add Action button.
28. In the Action dialog, select Submit Using a Data Connection.
29. Click the Add button.
30. In the data connection wizard, select to create a new data connection to submit data and click the Next button.
31. On the next screen select the option to submit the data To the Hosting Environment so the form will be submitted back to the SharePoint workflow process.
32. Click the Next button.
33. Click the Finish button.
34. In the Action dialog, click the OK button.
35. In the Rules dialog, click the Add Action button.
36. Select Close the Form from the drop-down list.
37. Click the OK button.
38. In the Rule dialog, click the OK button.
39. In the Rules dialog, click the OK button.
40. In the Button Properties dialog, click the OK button.
41. Save the form to a temporary working directory as TaskForm.xsn. Figure 3 shows the completed workflow action form.
Figure 3. The workflow task form
Adding the Item Schema
When the task form is presented to the user, we will need to populate it with the data used in the association and initiation forms. In order to do this, we must create a schema that represents the incoming data and attach it to the task form as a secondary data source. This will allow the form to properly display the information. The process for defining the secondary data source requires you to create a very specific XML file and then attach it to the form. The schema of this file is dictated by the workflow infrastructure.
1. Open a copy of Notepad and enter the following code. This code defines the fields that are available from the association and initiation forms:
<z:row xmlns:z="#RowsetSchema" ows_ReviewNotes="" />
2. Save the file as ItemMetadata.xml to a temporary working directory.
3. Open TaskForm.xsn in design mode if it’s not already open.
4. In the Design Tasks pane, click the Data Source link.
5. Click the Manage Data Connections link.
6. In the Data Connections dialog, click the Add button.
7. In the data connection wizard, select to create a connection to receive data.
8. Click the Next button.
9. On the next screen of the wizard, select the XML Document option and click the Next button.
10. Click the Browse button.
11. In the Open dialog, locate the ItemMetadata.xml file, select it, and click the Open button.
12. Click the Next button.
13. On the next screen of the wizard, ensure that the option labeled Include the Data Source as a Resource File in the Form Template or Template Part is selected.
14. Click the Next button.
15. On the next screen, ensure the box labeled Automatically Retrieve Data When Form Is Opened is checked and that the connection is named ItemMetadata. Then click the Finish button.
16. In the Data Connections dialog, click the Close button.
17. In the Action form, right-click the ReviewNotes text box and select Properties from the context menu.
18. Click the formula (fx) button under the Default Value section.
19. In the Insert Formula dialog, click the Insert Field or Group button.
20. In the Select a Field or Group dialog, select ItemMetadata (secondary) from the drop-down list.
21. Select the ows_reviewComments node and click the OK button.
22. In the Insert Formula dialog, click OK.
23. In the Field or Group Properties dialog, click OK.
24. Save the form and close InfoPath.
Creating the Workflow Project
The Visual Studio project you create for a workflow implements all of the functionality required to automate a process. In this exercise, you will simply be assigning a task to the manager to perform the employee review.
1. Start Visual Studio 2008.
2. From the main menu, select File >>New Project.
3. In the New Project dialog make sure that .NET Framework 3.5 is selected.
4. Click on Visual C#>>Workflow in the Project Types tree.
5. Select SharePoint 2007 Sequential Workflow in the Templates window.
6. Enter ReviewFlow2008 in the Name field and pick a suitable location to develop the project.
7. Click the OK button.
8. In the workflow wizard, enter the URL of the Team Site where you will deploy the workflow and click the Next button.
9. Check the box titled Automatically Associate Workflow.
10. In the Library or List field, select Employees.
11. In the History List field, select Workflow History.
12. In the Task List field, select Review Tasks.
13. Click the Next button.
14. In the final screen, check only the box titled Manual By Users.
15. Click the Finish button.
16. When the project is created, save it and close Visual Studio. You must perform a few additional steps with the InfoPath forms before you can proceed to code the project.
Publishing the Forms
Once you have created the workflow project, you must publish the workflow forms to the workflow project directory. This is required to support the deployment of the forms as part of the workflow feature you will create. This will allow you to deploy the forms along with the workflow assembly.
1. Open the form AssocForm.xsn in design mode in InfoPath.
2. In the Design Tasks pane, click the Design Checker link.
3. In the Design Checker pane, click the Change Compatibility Settings link.
4. In the Form Options dialog, check the box labeled Design a Form Template That Can Be Opened in a Browser or in InfoPath.
5. Enter the URL of a server running InfoPath Forms Services (e.g., http://moss) that can be used to validate the form design.
6. Click the Security and Trust Category.
7. Uncheck the box labeled Automatically Determine Security Level.
8. Select the Domain option.
9. Click the OK button.
10. In the Design Checker pane, click the Design Tasks link.
11. In the Design Tasks pane, click the Publish Form Template link.
12. In the first step of the Publishing Wizard, select to publish the form to a network location and click the Next button.
13. In the next step, click the Browse button.
14. In the Browse dialog, locate the directory where the file Workflow1.cs resides. This is the folder where the workflow project was created. The workflow forms must be published here.
15. Enter AssocForm.xsn in the File Name field and click the OK button.
16. In the Publishing Wizard, click the Next button.
17. In the next screen, clear the alternate access path and click the Next button. The workflow forms must only be accessed through the workflow process in SharePoint.
18. On the final screen, click the Publish button.
19. Close the wizard.
20. Repeat these steps to publish the InitForm.xsn and the TaskForm.xsn.
Developing the Project
Developing the workflow project is a combination of placing activities on the workflow design canvas and writing code behind them. Each activity you place on the canvas must be configured using various properties and then associated with a method in the code. In this project, you use the activities and code to receive information from the initialization form and create a new task.
1. Open the ReviewFlow2008 project in Visual Studio 2008.
2. In the Solution Explorer, right-click Workflow1.cs and select View Designer from the context menu.
The CreateTask Activity
This workflow begins by creating a task and assigning values to it. Creating the task is done by using the CreateTask activity. This activity must be configured so that it is properly managed by the workflow activity and has a unique identifier and a mechanism for accessing the fields in the task item. In this section, you will use the CreateTask activity to create the new task item:
1. Drag a CreateTask activity from the toolbox and drop it on the node just below the onWorkflowActivated1 activity.
2. Right-click createTask1 and select Properties from the context menu.
3. In the Properties window, set the CorrelationToken property to taskToken and hit the Enter key. This token is used to keep track of the particular task item in the workflow as multiple instances of the workflow are run by SharePoint. This token must be shared by all activities involved with the task item.
4. In the Properties window, set the OwnerActivityName (located under the CorrelationToken property) to Workflow1. This is the name of the workflow class that was created for your project. Assigning the task to this activity ensures that lifetime of the process components is properly managed.
5. In the Properties window, click the ellipses associated with the TaskId property.
6. In the Bind dialog, click the Bind to a New Member tab.
7. On the Bind to a New Member tab, select the Create Field option. This will create a simple member variable in your code. The taskId variable will uniquely identify the task you are creating.
8. Enter taskId in the New Member Name field and click the OK button.
9. In the Properties window, click the ellipses associated with the TaskProperties property.
10. In the Bind dialog, click the Bind to a New Member tab.
11. On the Bind to a New Member tab, select the Create Field option. This will create a simple member variable in your code. The taskProperties variable will contain information about the task that is created.
12. Enter taskProperties in the New Member Name field and click the OK button.
13. On the design canvas, right-click the CreateTask activity and select Generate Handlers from the context menu. This will create a new method that runs when the task is created. You will code this later. Figure 4 shows the workflow designer as it should appear at this point with the key property values visible. Check your work carefully against this image to avoid issues later.
Figure 4. The CreateTask activity
The While Activity
Once the task is assigned, the workflow must wait until the user completes it. The While activity establishes a loop that checks the task to see if it is complete before continuing. The While activity will contain an OnTaskChanged activity that you will use to check the task to see if it is completed after it has been changed.
1. Drag a While activity from the toolbox and drop it on the node just below the createTask1 activity.
2. Right-click the While activity and select Properties from the context menu.
3. In the Properties window, set the Condition to CodeCondition. This will allow you to specify a variable in code that will be used to determine whether the task is completed.
4. Expand the Condition property and type notComplete in the field and hit the Enter key. This will create a method you can use to determine whether the task is completed. You’ll code this method later.
5. Click the Workflow1.cs [Design] tab to return to the design canvas.
6. Drag an OnTaskChanged activity from the toolbox and drop it on the While activity.
7. Right-click the onTaskChanged1 activity and select Properties from the context menu.
8. In the Properties window, set the CorrelationToken property to taskToken.
9. In the Properties window, click the ellipses associated with the AfterProperties property.
10. In the Bind dialog, click the Bind to a New Member tab.
11. Enter afterProperties in the New Member Name field.
12. Select the Create Field option to create a member variable that will allow you to access the values of the task item after it has been changed.
13. Click the OK button.
14. In the Properties window, click the ellipses associated with the BeforeProperties property.
15. In the Bind dialog, click the Bind to a New Member tab.
16. Enter beforeProperties in the New Member Name field.
17. Select the Create Field option to create a member variable that will allow you to access the values of the task item before it has been changed.
18. Click the OK button.
19. In the Properties window, click the ellipses associated with the TaskId property.
20. In the Bind dialog, click the Bind to an Existing Member tab.
21. Select taskId from the list and click the OK button.
22. On the design canvas, right-click the OnTaskChanged activity and select Generate Handlers from the context menu. This will create a new method that runs when the task is changed. You will code this later. Figure 5 shows the workflow designer as it should appear at this point with the key property values visible. Check your work carefully against this image to avoid issues later.
Figure 5. The While activity
The CompleteTask Activity
The CompleteTask activity is used to take action after the task is completed. Using this activity would allow you to initiate further steps in the process or interact with other systems. In this exercise, you’ll simply add the activity to complete the workflow.
1. Drag a CompleteTask activity from the toolbox and drop it just below the While activity.
2. Right-click the CompleteTask activity and select Properties from the context menu.
3. In the Properties window, set the CorrelationToken property to taskToken.
4. In the Properties window, click the ellipses associated with the TaskId property.
5. In the Bind dialog, click the Bind to an Existing Member tab.
6. Select taskId from the list and click the OK button.
7. On the design canvas, right-click the TaskComplete activity and select Generate Handlers from the context menu. This will create a new method that runs when the task is completed. You will code this later. Figure 6 shows the workflow designer as it should appear.
Figure 6. The CompleteTask activity
Coding the Project
Once you have finished configuring the activities on the designer, you are ready to code the workflow. Coding the workflow involves retrieving the initialization data, settings task properties, and waiting for the task to complete. I have provided the complete solution code in Listing 1 for reference. The blue sections represent code that was added to the project. Red sections represent code that is unique to your project and must be changed to your specific value.
Listing 1. The Complete Workflow Code
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using System.Xml.Serialization;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
using Microsoft.Office.Workflow.Utility;
using System.Diagnostics;
namespace ReviewFlow2008
{
public sealed partial class Workflow1: SequentialWorkflowActivity
{
public Workflow1()
{
InitializeComponent();
}
//Workflow activated
public Guid workflowId = default(System.Guid);
public string managerUsername = default(string);
public string managerFullname = default(string);
public string reviewType = default(string);
public string reviewComments = default(string);
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties
workflowProperties = new
Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties();
private void onWorkflowActivated1_Invoked(
object sender, ExternalDataEventArgs e)
{
try
{
//Save the identifier for the workflow
workflowId = workflowProperties.WorkflowId;
// InitiationData comes from the initialization form
XmlDocument document = new XmlDocument();
document.LoadXml(workflowProperties.InitiationData);
XmlNamespaceManager ns = new XmlNamespaceManager(document.NameTable);
ns.AddNamespace("my","http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-10-25T13:38:03");
managerUsername = document.SelectSingleNode("/my:myFields/my:managerUsername", ns).InnerText;
managerFullname = document.SelectSingleNode("/my:myFields/my:managerFullname", ns).InnerText;
reviewType = document.SelectSingleNode("/my:myFields/my:reviewType", ns).InnerText;
reviewComments = document.SelectSingleNode("/my:myFields/my:reviewComments", ns).InnerText;
}
catch (Exception x)
{
logMessage(x.Message, EventLogEntryType.Error);
}
}
//Task Created
public Guid taskId = default(System.Guid);
public SPWorkflowTaskProperties taskProperties = new
Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
private void createTask1_MethodInvoking(object sender, EventArgs e)
{
try
{
// Create unique task ID
taskId = Guid.NewGuid();
//Set task properties
taskProperties.AssignedTo = managerUsername;
taskProperties.Description = reviewComments + "/n";
taskProperties.Title = "Perform employee review [" + reviewType + "]";
//Populate the action form using the secondary data source
taskProperties.ExtendedProperties["ReviewComments"] = reviewComments;
}
catch (Exception x)
{
logMessage(x.Message, EventLogEntryType.Error);
}
}
//Looping
private bool complete = false;
private void notComplete(object sender, ConditionalEventArgs e)
{
e.Result = !complete;
}
//Task Changed
public SPWorkflowTaskProperties afterProperties = new
Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
public SPWorkflowTaskProperties beforeProperties = new
Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
{
try
{
complete = bool.Parse(afterProperties.ExtendedProperties["ReviewCompleted"].ToString());
}
catch (Exception x)
{
logMessage(x.Message, EventLogEntryType.Error);
}
}
//Task Completed
private void completeTask1_MethodInvoking(object sender, EventArgs e)
{
try
{
afterProperties.Description +=
afterProperties.ExtendedProperties["ReviewNotes"].ToString();
afterProperties.PercentComplete = 100;
}
catch (Exception x)
{
logMessage(x.Message, EventLogEntryType.Error);
}
}
//Logging
private void logMessage(string message, EventLogEntryType type)
{
if (!EventLog.SourceExists("SharePoint Workflow"))
EventLog.CreateEventSource("SharePoint Workflow", "Application");
EventLog.WriteEntry("SharePoint Workflow", message, type);
}
}
}
Coding onWorkflowActivated1_Invoked
This method runs when the workflow is started. The InitiationData property of the workflowProperties object contains the XML data from the initialization form. Therefore, you can load this into an XmlDocument object and retrieve all of the values from the form. In this exercise, you simply store these values in variables for later use.
When you code this part of the solution, be sure to use the correct namespace and XPath values. Yours may be different than what is shown in Listing 1. You can get the XPath for any field by right-clicking it in the task pane in InfoPath and selecting Copy XPath from the context menu. In order to get the namespace for the form, select Properties from the same menu and click the Details tab on the Properties dialog.
You should also notice that I have placed error handling in all of the routines. If an error occurs, I log it to the Application event log. This technique can save you hours of painful debugging.
Coding createTask1_MethodInvoking
This method runs when a new task needs to be created. In this case, you are simply setting the values for the task item. Additionally, you use the ExtendedProperties collection to access the action form. Since the action form is associated with the task item, the extended properties will let you read or write to the form fields.
Coding the Loop
The notComplete method runs whenever the loop needs to check and see if it should continue or break. This code simply returns the opposite of the reviewCompleted field. This field is saved to a member variable in the TaskChanged1_MethodInvoked method.
Coding completeTask1_MethodInvoking
This method runs when the task is completed. In this code, the task is updated with the notes from the review. It is also set to be 100% complete. After this code runs, the workflow will show that it is completed in SharePoint.
Associating the InfoPath Forms with the Workflow
In order to test the workflow, you must first associate the InfoPath forms you created earlier with the workflow project. In order to associate the InfoPath forms with the workflow, you must edit the Feature.xml and Workflow.xml files. These files are already included in the project, so you can simply add the necessary information.
1. Open Feature.xml in Visual Studio.
2. In the ElementsManifest section, add the following code beneath the workflow.xml reference.
<ElementFile Location="AssocForm.xsn"/>
<ElementFile Location="InitForm.xsn"/>
<ElementFile Location="TaskForm.xsn"/>
Here is the complete listing of the Feature.xml file.
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="a6d5a2df-e959-4d62-89d3-36f6b6c11556"
Title="ReviewFlow2008 feature"
Description="My SharePoint Workflow Feature"
Version="12.0.0.0"
Scope="Site"
ReceiverAssembly="Microsoft.Office.Workflow.Feature, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
ReceiverClass="Microsoft.Office.Workflow.Feature.WorkflowFeatureReceiver"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="workflow.xml" />
<ElementFile Location="AssocForm.xsn"/>
<ElementFile Location="InitForm.xsn"/>
<ElementFile Location="TaskForm.xsn"/>
</ElementManifests>
<Properties>
<Property Key="GloballyAvailable" Value="true" />
<!-- Value for RegisterForms key indicates the path to the forms relative to feature file location -->
<!-- if you don't have forms, use *.xsn -->
<Property Key="RegisterForms" Value="*.xsn" />
</Properties>
</Feature>
In the Workflow.xml file, the AssociationUrl, InstantiationUrl, and ModificationUrl attributes refer to the pages that will host your InfoPath forms in the workflow. The TaskListContentTypeId is the ID of the content type that will be used for the workflow task. This value is always the same and referes to the default MOSS workflow task type. Additionally, there are specific identifiers included in the MetaData section for each form. These are the unique identifiers assigned by InfoPath and they can be retrieved by opening the form in design mode and selecting File >>Properties from the menu in the Solution Explorer. Finally, I have included some default Association data that you can use to ensure the workflow runs during debugging.
1. Open Workflow.xml in Visual Studio.
2. In the Workflow element, the following code to specify the forms and content type to use with the workflow.
TaskListContentTypeId="0x01080100C9C9515DE4E24001905074F980F93160"
AssociationUrl="_layouts/CstWrkflIP.aspx"
InstantiationUrl="_layouts/IniWrkflIP.aspx"
ModificationUrl="_layouts/ModWrkflIP.aspx"
3. In the MetaData section, add code similar to what is shown below, but use the form identifiers associated with your forms.
Caution: Make sure each entry is on a single line with no white space. Strange errors can occur if you include line breaks in these entries.
<Association_FormURN>[URN]</Association_FormURN>
<Instantiation_FormURN>>[URN]</Instantiation_FormURN>
<Task0_FormURN>[URN]</Task0_FormURN>
4. Add an AssociationData element to provide default association data for the workflow.
<AssociationData>
<my:myFields xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:my=http://schemas.microsoft.com/office/infopath/2003/myXSD/2008-04-02T11:46:38
xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-us">
<my:ManagerGroup>
<my:Person>
<my:DisplayName>CHIMPCO\Administrator</my:DisplayName>
<my:AccountId>CHIMPCO\administrator</my:AccountId>
<my:AccountType>User</my:AccountType>
</my:Person>
</my:ManagerGroup>
<my:ReviewType>Annual</my:ReviewType>
<my:ReviewComments></my:ReviewComments>
</my:myFields>
</AssociationData>
Here is the complete listing of the Workflow.xml file.
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Workflow
Name="ReviewFlow2008"
Description="My SharePoint Workflow"
Id="091c629f-6768-4a41-ba8a-dbd351ab795d"
CodeBesideClass="ReviewFlow2008.Workflow1"
CodeBesideAssembly="ReviewFlow2008, Version=1.0.0.0, Culture=neutral, PublicKeyToken=193643fe2dff5452"
TaskListContentTypeId="0x01080100C9C9515DE4E24001905074F980F93160"
AssociationUrl="_layouts/CstWrkflIP.aspx"
InstantiationUrl="_layouts/IniWrkflIP.aspx"
ModificationUrl="_layouts/ModWrkflIP.aspx">
<Categories/>
<AssociationData>
<my:myFields xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:my=http://schemas.microsoft.com/office/infopath/2003/myXSD/2008-04-02T11:46:38
xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-us">
<my:ManagerGroup>
<my:Person>
<my:DisplayName>CHIMPCO\Administrator</my:DisplayName>
<my:AccountId>CHIMPCO\administrator</my:AccountId>
<my:AccountType>User</my:AccountType>
</my:Person>
</my:ManagerGroup>
<my:ReviewType>Annual</my:ReviewType>
<my:ReviewComments></my:ReviewComments>
</my:myFields>
</AssociationData>
<MetaData>
<!-- Tags to specify InfoPath forms for the workflow; delete tags for forms that you do not have -->
<Association_FormURN>urn:schemas-microsoft-com:office:infopath:AssocForm:-myXSD-2008-04-02T11-46-38</Association_FormURN>
<Instantiation_FormURN>urn:schemas-microsoft-com:office:infopath:InitForm:-myXSD-2008-04-02T11-46-38</Instantiation_FormURN>
<Task0_FormURN>urn:schemas-microsoft-com:office:infopath:TaskForm:-myXSD-2008-04-02T13-05-24</Task0_FormURN>
<StatusPageUrl>_layouts/WrkStat.aspx</StatusPageUrl>
<AssociateOnActivation>false</AssociateOnActivation>
</MetaData>
</Workflow>
</Elements>
Once you have the files edited, you can deploy the feature. First build the assembly by selecting Build>>Build ReviewFlow2008. Once the project builds successfully, deploy it to the test site by selecting Build>>Deploy ReviewFlow2008.
Tip If you have errors and need to redeploy the workflow, deactivate and uninstall the workflow completely. Then make your changes and try again. Never force a workflow to install over an existing installation because it can cause issues with the InfoPath form versioning that may prevent the workflow from executing.
Testing the Workflow
In order to debug the workflow, simply set break points and run it from within Visual Studio. Visual Studio will automatically deploy the workflow, attach to the appropriate process, and open the target site. You should be able to start a performance review for a person on the Employees list. Verify that your initialization form appears and that a new task is created. Then complete the task and verify it works as expected. Be sure to check the event log for any errors.
转自http://scothillier.spaces.live.com/Blog/cns!8F5DEA8AEA9E6FBB!410.entry