124
September 2009

Tutorial Share Point Happy Birthday Workflow Slideshare

Embed Size (px)

DESCRIPTION

Tutorial on creating a SharePoint workflow that sends a Happy Birthday card (as a content type) that is paritally populated using an InfoPath form. It is then emailed to the recipient of the card. The interesting part is the disabling of the InfoPath form once the workflow is completed by using a secondary data source.

Citation preview

Page 1: Tutorial Share Point Happy Birthday Workflow Slideshare

September 2009

Page 2: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 2 of 108

ContentsSUMMARY.......................................................................................................................3

DESCRIPTION OF THE WORKFLOW............................................................................3

SUMMARY SNAPSHOTS OF OUR WORKFLOW..........................................................4

OVERVIEW OF THIS TUTORIAL..................................................................................12

STEPS INVOLVED IN THE PROCESS.........................................................................12

SOFTWARE REQUIRED TO DUPLICATE THIS PROJECT.........................................13

STEP 1 – CREATE A NEW LIBRARY IN SHAREPOINT..............................................13

STEP 2 – CREATE A TEMPLATE FOR THE BIRTHDAY CARD..................................17

STEP 3 – CREATE THE WORD DOCUMENT FOR THE BIRTHDAY CARD FROM WITHIN THE LIBRARY..................................................................................................20

STEP 4 – CREATE OUR INFOPATH 2007 FORM TO ACCEPT INPUT FROM THE USERS...........................................................................................................................35

STEP 5 – CODE OUR WORKFLOW IN VISUAL STUDIO............................................70

STEP 6 – CONFIGURE WORKFLOW.XML AND FEATURE.XML IN VISUAL STUDIO.......................................................................................................................................92

CONCLUSION...............................................................................................................95

Page 3: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 3 of 108

SUMMARY

This tutorial will demonstrate how to create a SharePoint sequential workflow that will reveal many useful techniques that can be applied in the field. The purpose of this workflow is to send a Birthday Card (as a Word document) via Email to a SharePoint user with some of the text of the Birthday Card filled out dynamically in C# code during the workflow. The dynamically populated fields will get their input from an InfoPath form presented to the person who is assigned the task of signing the card. This is similar to what might happen in an office today when your supervisor wants a person in his/her group to send a birthday card to a particular birthday boy or girl. In our situation, the supervisor creates the card from a SharePoint library as a Word document (as a content type) which has a workflow attached to it. The difference here is that the process is under the management of the workflow which we will code in Visual Studio 2008.

Note: This is a long tutorial with a vast number of steps required to complete it. The reader should be alert to how complex the process is to create a very simple sequential workflow that does some fancy work behind the scenes using InfoPath forms.

DESCRIPTION OF THE WORKFLOW

Let’s take a moment to better describe what we want. A birthday card will be created as a content type for a SharePoint library that we will create. We will call the library Happy Birthday Card Library. A birthday card will be a Word document, with a picture of a birthday cake, and several pre-defined fields as Word properties which are linked to column types in the library. Some of these fields will be filled out by the initiator of the birthday card (the supervisor most likely) which will include the name of the recipient (E.g. “Jane Smith”), an opening greeting (E.g. “Best wishes on your Birthday!”), the email address of the recipient, and the login name of the person assigned the task of signing the card (E.g. [email protected]). There will then be two additional fields which need to be populated by the signer of the card. These two fields are filled out by using an InfoPath form. These fields are from (E.g. “John”) and the message the signer would like to include (E.g. “Hope you like the cake!”). When the signer completes the workflow task, the workflow will finish populating the Word document Birthday Card with the two fields obtained from the InfoPath form, and then email the updated Birthday Card to the recipient as an email attachment. The workflow will then mark the task as completed. The other thing we will do is disable the submit button on the InfoPath form when the workflow task is completed. If we did not do this, then the user could re-submit the form again and again from the Tasks page. There will have to be a feedback mechanism for the InfoPath form to make it aware that the task was completed. We disable the submit button in this example.

Page 4: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 4 of 108

Page 5: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 5 of 108

SUMMARY SNAPSHOTS OF OUR WORKFLOW

For reference, the snapshots below summarize the procedure of sending the birthday card.

1. Administrator creates a Birthday Card (Figure 1)

Figure 1

2. Administrator fills out 4 properties of the Word document (Figure 2)

Page 6: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 6 of 108

Figure 2 – Creator fills out 4 fields in the Word properties boxes

Note that Mary Smith was assigned the task of signing the card (E.g. Assigned To Login Name = MY_NETBIOS_NAME\marysmith in the property field Figure 2)

3. Exit Word (Figure 3)

Page 7: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 7 of 108

Figure 3 - Exit Word

Page 8: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 8 of 108

4. Birthday Card is saved in the SharePoint Library (Figure 4)

Figure 4

5. Workflow is stated automatically on save. ( Figure 5)

Figure 5 – Our workflow has started.

6. We now sign in as Mary Smith, signer of the card. The task is present on her task list. (Figure 6)

Page 9: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 9 of 108

Figure 6 – We are now signed in as Mary Smith

7. Mary clicks “Please sign this birthday card” and gets the InfoPath form which she fills out 2 fields. (Figure 7)

Figure 7 – Mary fills out the form.

8. Mary clicks the submit button and the task completes. (Figure 8)

Figure 8 – Task completed!

Page 10: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 10 of 108

9. Recipient of the card gets an email with the filled out Birthday Card. (figure 9 & 10)

Figure 9

Figure 10

10. Word document is fully populated by our Workflow. (Figure 11)

Page 11: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 11 of 108

Figure 11 – Card filled out by the Workflow!

Page 12: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 12 of 108

11.Notice that we disable the Submit button in the InfoPath form if Mary tries to fill it out a 2nd time. (Figure 12).

Figure 12 – Submit button is disabled via feedback from the Workflow on subsequent tries

So, that’s the flow. It’s very simple from the user’s perspective. However, to get all this working requires a considerable amount of knowledge and work. Let’s get started.

Page 13: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 13 of 108

OVERVIEW OF THIS TUTORIAL

This tutorial has a huge number steps that need to be performed to set up this workflow. There is very little C# code in the Workflow, and most of the work is done outside of the workflow programming in preparation. Also, this tutorial is quite long since there are so many pieces that need to be discussed to get all of this to work together. Also, there are some issues that would need to be addressed in a production environment. One of them is that we only have one Word document Birthday Card in our SharePoint library. Our C# code references this Word document by its filename and is hard coded. We would need to enhance the C# code to allow any filename to be used for a Birthday Card. One way to do this is to include another property on the Birthday Card Word document named Filename which the initiator of the card would fill out. Another issue is that our InfoPath form takes over the page where a user would normally change the % complete and status of the Workflow. That is why we update the completed status in the Workflow rather than let the user do it manually. Students of SharePoint Minds are encouraged to modify this Workflow to address those issues.

In any event, this tutorial has a wealth of good information regarding SharePoint workflows that would be helpful.

STEPS INVOLVED IN THE PROCESS

To create this work flow, we have to perform the following steps:

1. Create a new library in SharePoint named Happy Birthday Card Library.2. Create a template for the Birthday Card in the library by defining new columns.3. Create the Word document Birthday Card.4. Add the Birthday Card as a content type to the library.5. Create our InfoPath 2007 task form to accept user input for the From and

Message fields.6. Configure the InfoPath form to receive feedback from the workflow by specifying

a secondary data source.7. Configure the InfoPath form to be presented in a web page with Full Trust

security and temporary certificate.8. Code the Workflow using Visual Studio 2008 in C#.9. Configure the Workflow in Visual Studio to include the InfoPath form as part of

the deployment.10.Configure the Workflow.xml file so that our InfoPath form is presented to the user

in a web page.11.Configure feature.xml so that our InfoPath form is deployed as a feature.

Page 14: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 14 of 108

NOTE: It should be noted that this author created this library under the Team Site tab of his main portal SharePoint site. This means that the columns that we create (E.g. To, From, Greeting, Assigned to Login Name, Email Address, Completed, and Message) in our Happy Birthday Library are not global site columns, but local to the Team Site.

SOFTWARE REQUIRED TO DUPLICATE THIS PROJECT

The software requirements for this project are significant. The software that you will need is as per the following list:

1. Microsoft ASP.NET 3.5 Framework2. Microsoft Windows Server 2003 installed on the Virtual Machine (E.g. the VM)3. Ability of the virtual machine to connect to the internet using the Microsoft

Loopback adapter (see the document on this topic by this author on the SharePointMinds.com site).

4. Microsoft SharePoint 20075. Microsoft SQL Server 2005 (required by SharePoint)6. Microsoft Visual Studio 2008 7. Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions, Version

1.28. InfoPath Forms 2007 9. Visual Studio Tools for Applications 200710. Microsoft Word 2007

STEP 1 – CREATE A NEW LIBRARY IN SHAREPOINT

On your SharePoint site (in this case, the authors Team Site), click Site Actions > Create as shown in Figure 13.

Page 15: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 15 of 108

Figure 13

Page 16: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 16 of 108

On the resulting page, click Document Library as shown in Figure 14.

Figure 14

Page 17: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 17 of 108

Fill out the form for the new library and Click Create. Refer to Figure 15.

Figure 15

This will result in a new library as shown in Figure 16.

Figure 16

This completes the creation of our library.

Page 18: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 18 of 108

STEP 2 – CREATE A TEMPLATE FOR THE BIRTHDAY CARD

In this step, we are going to create several new columns. These columns will be available in the Happy Birthday Card Word document that we create and will become Word document objects. SharePoint will take care of the linking for us. We will be able to access the contents of the Word objects in the C# code behind. That means that we can read the fields, but it also means that we can write to the fields in the C# code behind in the Workflow. Therefore, the Word document serves as an input form where we can enter values in the fields. It is intended that only 4 of the fields are filled out when the administrator creates a new Birthday Card (E.g. To, Greeting, Assigned To Login Name, Email Address). The remaining fields will be filled out in C# code using data from the InfoPath form.

In the Happy Birthday Card Library, click Settings > Document Library Settings as shown in Figure 17.

Figure 17

Now we want to create some new columns for our Birthday Card. We are going to have to repeat the process for each of our columns. Column names in red are required fields to be filled out by the creator of the card. Our columns are:

1. To2. Greeting3. From4. Message5. Email Address

Page 19: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 19 of 108

6. Assigned To Login Name7. Completed

The first four columns will be filled out by the person who starts the Birthday Card process from the library. That is, when he/she creates new instance of the Birthday Card by clicking the New > Happy Birthday Card menu selection in the library.

To: will be the name of the person who will receive the Birthday Card. Example: To: Jane Smith

Initial Greeting: The second line will be the initial greeting which is the basic text of the card to be displayed. Example: Happy Birthday Jane!

Email Address: The email address of the recipient of the card.

Assigned To Login Name: The ID of the person assigned the task of signing the card and providing a message. Example: yourdomain\johnsmith

The remaining columns will be filled out dynamically by the workflow that we will code. The content of the remaining columns will be obtained from information that is submitted when the signer completes their workflow task by filling out an InfoPath 2007 form during the workflow process.

So now let’s add come columns. We will only show the process for the first column. The rest of the columns will follow the same procedure.

Click Create Column as shown in Figure 18.

Page 20: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 20 of 108

Figure 18

The resulting page is shown in Figure 19. Fill out the form as shown in Figure 19.

NOTE: All the fields will be single line of text for all our columns. Also, four of the fields will be required fields, so check the radio button to make it a required field. Recall that we denoted the required columns in red above.

Figure 19

Repeat this process for our remaining columns. The final result showing all columns created should appear as shown in Figure 20 (except for title which was there already).

Page 21: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 21 of 108

Figure 20 – Our 7 columns added

STEP 3 – CREATE THE WORD DOCUMENT FOR THE BIRTHDAY CARD FROM WITHIN THE LIBRARY

Return to the Birthday Card Library in SharePoint. From the New > New Document menu selection, create a new Word document (which will be aware of our columns template that we just created). Refer to Figure 21.

Page 22: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 22 of 108

Figure 21

An instance of a blank Word document will appear and will show our columns template as shown in Figure 22.

Figure 22 – Note the text boxes, 4 with red asterisks denoting required fields

Next, convert the Word document as shown in Figure 23 and Figure 24.

NOTE: You must convert the document or you will not be able to create the objects that are linked to the 7 site columns that we created.

From the main menu, click Convert. A dialog will appear as in Figure 24. Click OK.

Page 23: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 23 of 108

Figure 23

Figure 24

Now we must save the document to a directory on disk. Do not save the document in the SharePoint library which is the default. Save it to a directory of your choice on disk. To save the document, this author navigated to his My Documents directory as shown in Figure 25.

Page 24: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 24 of 108

Figure 25

Next, we added a Happy Birthday text at the top and added a picture as shown in Figure 26. Once you have done this, save the document (again).

Page 25: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 25 of 108

Figure 26 – We added a picture and Happy Birthday as text

Now we need to add some Word Objects to our document in the body just below the picture of the cake. We will perform the following procedure for all of our columns in turn.

Place the cursor in Word where you would like to create the To object (just below the cake for this one). Then, Click the Insert tab, then Quick Parts > Document Property. Refer to Figure 27.

Page 26: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 26 of 108

Figure 27 – An object corresponding to the menu item To will be placed at the cursor.

On the resulting dropdown, scroll down to the To listing and click it. This will cause the To object to be inserted at the cursor in the Word document as shown in figure 28.

Page 27: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 27 of 108

Figure 28 – Our To object was inserted at the cursor in Word

NOTE: These objects in Word will be available in our C# code behind in the workflow. We can either read from them, or write to them in code.

Perform these steps again in turn, for our remaining objects. When finished, the Word document should appear as in Figure 29.

Page 28: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 28 of 108

Figure 29 – 4 of 7 of our template columns are now objects in the body of the Word document. We never show the other 3 properties on the card.

Our Word document is now finished. Click save (remember not to save in the SharePoint library, save it to the same directory you have been using), and then exit Word by clicking Exit Word as shown in Figure 30.

Page 29: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 29 of 108

Figure 30 – Exit Word

Figure 31 – Saving the completed document

We now need to add our Happy Birthday Word document to our library. To do that, navigate to our Happy Birthday Library, and click Actions > Open in Windows Explorer as shown in Figure 32.

Page 30: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 30 of 108

Figure 32

When explorer opens, click on the Forms icon, and then you should see the various forms as shown in Figure 33. We need to copy and paste our Happy_Birthday_Card.docx file to this directory. To do that, navigate to the location where you saved the Word document, copy it, and navigate back to this directory and paste it. The result should be as shown in Figure 34.

Figure 33 – We need to add our Word document here

Page 31: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 31 of 108

Figure 34 – Are new Word document pasted into the directory

Next, click on Settings > Document Library Settings as shown in Figure 35.

Figure 35

We now need to add the content type for our Happy Birthday Card Word document to the library. As shown in Figure 36, click on Add from existing content types.

Note: if your page does not show the Content Types section, refer to Appendix A to get it to display.

Page 32: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 32 of 108

Figure 36

Now, using Figure 37, find the content type Birthday Card in the left hand list box, and add it to the right hand list box.

Figure 37

Page 33: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 33 of 108

Note: The content type of Birthday Card should appear in the left hand list box because we placed our Word document in the Forms directory of the library. Your name may differ depending on what you saved the Happy Birthday Card Word document filename to.

We should now see a new content type in our library as shown in Figure 38.

Figure 38

NOTE: this author recommends that you change the order of the content types shown in Figure 38. Place the Birthday Card content type first, and move Document below it. You can reverse the order by clicking the link just below the red circle in Figure 38 (its cut off in the figure) called Change new button order and default content type.

Next, we need to specify the template to use for the Birthday Card content type. As shown in Figure 39, click on Advanced Settings.

Page 34: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 34 of 108

Figure 39

On the resulting page, add the URL of our Happy_Birthday_Card.docx file as shown in Figure 40. Remember we just pasted the document in the forms directory. Click OK.

Figure 40

Now, let’s check if our blank Birthday Card loads. As shown in Figure 41, click on New > Birthday Card

Page 35: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 35 of 108

Figure 41

Our Birthday Card Word document should open up as shown in Figure 42. If it does, all is well and we can move on to the next step. Close the Word document without saving it.

Figure 42

Page 36: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 36 of 108

This completes step 3.

QUESTION: Should our Happy Birthday Card been installed as part of the deployment process where a deployment package would be executed on each server in the farm?

ANSWER: Not necessarily. Remember that content types are stored in the content data base. It will therefore be available to all servers in the farm. So, installing it as we did here only need be done once.

STEP 4 – CREATE OUR INFOPATH 2007 FORM TO ACCEPT INPUT FROM THE USERS.

The purpose of this InfoPath form is to collect the name and birthday greeting from the person assigned the task of signing the card in the workflow. Also, we want it to be presented in a web page rather than in the InfoPath client (which is the default). We will have to specifically configure the InfoPath form to open in a web browser. We also will provide some validation. If either of the 2 fields are blank, we need to prevent the user from submitting the form. Also, we will need to provide the means to disable the Submit button if the workflow has been completed.

4.1 Open the InfoPath application and create a new blank form project

We now need to open the InfoPath application and create a new blank template as shown in Figure 43.

Page 37: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 37 of 108

Figure 43

4.2 – Add a basic layout to the form

On the resulting screen under Design Tasks, click on Layout as shown in Figure44.

Figure 44

Select the Table with Title layout. You should then see a new layout as shown in Figure 45.

Page 38: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 38 of 108

Figure 45

Change the title to Enter Birthday Card Message as shown in Figure 46.

Figure 46

This author changed the color scheme by clicking the navigation items as shown in Figure 47.

Page 39: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 39 of 108

Figure 47

4.3 – Add 3 rows and split them into 2 columns

Next, we add 2 rows beneath the title, and then we split those rows into 2 columns as shown in Figure 31. This is done by right clicking on the table, and selecting the appropriate menu items to add rows and split into 2 columns. Refer to Figures 48 & 49.

Figure 48

Page 40: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 40 of 108

Figure 49

4.4 Add a text box control to each row

From the right hand Task Pane as shown in Figure 50, click the drop down arrow and select Controls from the menu. We are now going to add a text box on each of our three rows in the table.

Figure 50

Drag a text box onto each row of our table as shown in Figure 51, and add the text in the left hand columns as shown.

Page 41: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 41 of 108

Figure 51

4.5 – Modify the names of the default DataSource fields assigned to our text boxes

NOTE: When you create a form template, Microsoft Office InfoPath automatically creates a default data source for you. All InfoPath form templates contain a single, default data source.  You add fields and groups to the main data source by using the Data Source task pane or by dragging a control from the Controls task pane onto a view in the form template. When you drag a control onto a view, InfoPath adds fields and groups to the default data source according to the type of control you are adding. For example, if you drag a text box control onto your form template, InfoPath adds a field to the main data source. In our case, we see three fields added to the default data source since we dragged three text boxes onto our form.

Figure 52 – Our default data source showing our three fields

We now want to rename our fields to have them correspond to what our text boxes are intended to contain. Right click on the first text box, and select Text Box Properties as shown in Figure 53.

Page 42: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 42 of 108

Figure 53

Change the name of the field to From, check the checkbox Cannot be blank and click OK. See Figure 54. Do the same for the 2nd text box, but enter the field name Message and click OK. Do the same for the 3rd text box but enter the name Completed, but do not check the checkbox Cannot be blank. Our form should look like Figure 55.

Figure 54

Also, from the Display tab, check the checkbox Read Only for the Completed text box. We do not want the user to be able to type in the Completed text box. We only want him/her to type in the From and Message text boxes.

Page 43: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 43 of 108

Figure 55

4.6 - Add a button to our form

We will need a button for the user to click after he/she has filled out the form. We add that now. From the Task Pane on the right, click to get the drop down, and then select Controls from the resulting menu. Drag a button onto our form as shown in Figure 56.

Figure 56

4.7 Preview our form to see how it looks.

Click on the Preview button on the menu bar. The preview should appear as in Figure 57.

Page 44: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 44 of 108

Figure 57 – Preview showing our red asterisks denoting cannot be blank

4.8 – Change the button title to Submit

Right click on the button, and click Button Properties from the menu. Enter the name Submit as shown in Figure 58. Click OK.

Figure 58

Page 45: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 45 of 108

4.9 – Add a rule to the button to disable it if the text boxes are blank

As in typical .NET programming, we need some validation when the button is clicked on the form. We need to make sure the user entered something in the text boxes. How about if we disable the button until the text boxes contain something? Right click on the button and click on Conditional Formatting as in Figure 59.

Figure 59

On the resulting dialog box, Click Add. This causes a 2nd dialog to appear as in Figure 60. Add the condition as shown in the Figure. Also, note that the checkbox Disable this control is checked. This means that if either text box is blank, our Submit button will be disabled.

Page 46: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 46 of 108

Figure 60 – if the condition is true, disable the button

We now have to add a rule that says when the Completed text box has a value of “1” (denoting the condition true), then we must disable the button in that case as well. So, add a second rule as we did for the first, except this time set the Conditional Format to that shown in Figure 61.

Figure 61

Page 47: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 47 of 108

We can now test the validation by using the Preview button on the menu bar. In preview mode, add some text to both text boxes. The button should go from the disabled state to the enabled state as shown in Figure 61.

Figure 61 – test our form in preview mode

4.10 – Add a rule to send data to the server when the button is clicked.

We now need to configure the button so that it sends data to the server when the button is clicked. To do that, right click on the button as we have done before, and we get the dialog box as shown in Figure 62.

Page 48: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 48 of 108

Figure 62

After you click the Rules button as shown in Figure 62, a new dialog will appear. On that dialog click Add to add a new rule. The resulting dialog will appear as in Figure 63.

Page 49: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 49 of 108

Figure 63

Click on the Set Condition button and a new dialog will appear. Here we are going to configure the button to send data to the server when the From and Message text boxes are populated and the button is clicked. Refer to Figure 64.

Page 50: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 50 of 108

Figure 64 – specify the condition

Click OK to get back to the previous dialog. On that dialog click on Add Action. In the resulting dialog, click on Submit using a Data Connection. Refer to Figure 65.

Figure 65 –specify the action for the condition

Page 51: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 51 of 108

Now we have to configure the connection. Click the Add button and a new Wizard will appear as in Figure 66.

Figure 66 –we are going to submit the data to the server

Select the defaults as shown in Figure 66 and click Next. The wizard will move to the next screen as shown in Figure 67.

Page 52: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 52 of 108

Figure 67

As shown in Figure 67, select To the hosting environment, such as an ASP.NET page or hosting application. Then click Next. The wizard will move to the next screen as shown in Figure 68.

Page 53: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 53 of 108

Figure 68 – accept the default name

Accept the defaults as shown in the Figure and click Finish. When the wizard disappears, we need to add another action to the button. Bring up the dialog as we have done before as shown in figure 69.

Page 54: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 54 of 108

Figure 69 – adding the action to close the form

Click on Add Action, and in the resulting dialog, click on Close the Form from the dropdown. The results should appear as in Figure 70.

Page 55: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 55 of 108

Figure 70

Keep clicking OK to close out all the dialog boxes. So, what we have configured is that when the text boxes have text, enable the button. When the button is clicked, submit the data to the server and close the form.

4.11 – Configure the form to receive data from the workflow on load.

When the form is submitted, the signer of the card enters text into the From and Message fields that are sent to the server. Our C# code behind in the workflow will read the data submitted and will cause the task to be changed to the completed state when this happens.

However, the signer of the card could go back to the task list and try to submit the form again. When he/she clicks the Please sign this birthday card link on subsequent tries on the SharePoint Tasks page, the form will load again, but we want to populate the form on these subsequent loads. This is the case where we want to disable the Submit button on the form, and additionally, we would like to populate the form with the values that were originally submitted by the signer. We don’t want to simply put up a blank form again. Remember, the form was already successfully submitted and the task was placed in the completed state.

So, to populate the form on subsequent loads, and also disable the Submit button, we need to configure a secondary data connection. This data connection will be a receive data connection.

Page 56: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 56 of 108

Adding the Receive Data Connection

NOTE: The creation of the ItemMetaData.xml file described in the following section was created by this author in the Workflow project in Visual Studio 2008, and the xml file is part of the solution files. It is recommended that you create a Visual Studio Workflow blank project, add an Xml file named ItemMetaData.xml and refer to that file in step 2 below. This tutorial will eventually get to create the workflow in VS2008. Refer to Figure 71. You don’t have to include the file in the project as this author has. You can simply save it to the directory of your choice if you want to.

Figure 71 – The authors VS2008 solution containing the ItemMetaData.xml file

1. We will want to update our task form from the workflow. To send data to the form fields from the workflow, we need to create a receive data connection. For this, we will use a very simple text (XML) file.

2. As noted above, create an Xml file in Visual Studio 2008. Name it: ItemMetadata.xml. The name is case-sensitive and any other name will not work (Watch the case of the ‘d’ character, it’s lowercase).

3. Inside this file place the following line of text: <z:row xmlns:z=”#RowsetSchema” ows_From=”” ows_Message=”” ows_Completed=”” />.

4. Save and exit the file. If, in future you want to pass other data back to a task form, just create a similar file and reference the fields in your form by adding ows_ before the field name. You can have multiple fields, separated by a space.

5. Back in InfoPath, select Data Connections from the Tools menu.6. Click the Add button and create a new data connection to receive data. A wizard

will start as shown in Figure 72.7. Select the radio button Receive Data as shown in Figure 72. Click Next.8. Select XML document as our data source and click Next. See Figure 73.9. In the next wizard screen, browse to ItemMetadata.xml file you just created and

select it. Note that it’s the file in our Visual Studio 2008 project. See figure 74 and 75. Click Next.

Page 57: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 57 of 108

10. IMPORTANT - As shown in Figure 76, select the radio button Include data as a resource file in the form or form template part. Click Next.

11.Leave the remaining settings at their default value and click Next until Finished.12.Back in the form, double-click on the From field. 13.We’re going to set the default value to that passed into the data connection via

the workflow. Click the Fx button next to the default value field as shown in Figure 78.

14.Click the Insert field or group button as shown in figure 79.15.From the Data Source drop-down, select ItemMetadata as shown in Figure

80.16.Select the ows_from field and click OK . Refer to Figure 80 again.17.The field should appear as shown in Figure 81. Click OK until all dialogs close.18.Repeat this process for the remaining two fields (E.g. Message and Completed)

Figure 72

Page 58: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 58 of 108

Figure 73

Page 59: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 59 of 108

Figure 74

Figure 75

Page 60: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 60 of 108

Figure 76

Page 61: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 61 of 108

Figure 77

Page 62: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 62 of 108

Figure 78

Page 63: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 63 of 108

Figure 79

Page 64: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 64 of 108

Figure 80

Page 65: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 65 of 108

Figure 81

Q. Where is the ItemMetaData.xml file after you reference it as a secondary data source?

A. It is embedded as a resource the InfoPath form. We specified this in Figure 76.

4.12 – Make the form browser compatible

We want our form to be displayed in a browser, not in the InfoPath client. That means that the form will appear in a web page in SharePoint. To do this, we have to make the form browser compatible.

On the top menu bar, click Tools > Form Options. A dialog box will appear as shown in Figure 82. On the left hand side, scroll down to Compatibility and click the check box Design a form template that can be opened in a browser or InfoPath. Then click OK.

Page 66: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 66 of 108

Figure 82

4.13 – Configure the forms Security and Trust settings

The form will be opened in a web page, and SharePoint will require that the form be trusted. We need to configure the Form so that SharePoint will allow it to be opened.

On the top menu bar in InfoPath, click Tools > Form Options. A dialog box will appear as shown in Figure 83. On the left hand side, scroll down to Security and Trust and click the radio button Full Trust. Then, check the checkbox Sign this form certificate. You will need to click the button Create Certificate during the process. This certificate will only be a temporary certificate for our development purposes. In practice, a real certificate may be required. When finished, the dialog should look like Figure 83.

Page 67: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 67 of 108

Note: This author found that SharePoint complained that the form was not trusted and would not allow it to be opened. Making the changes to Full Trust with certificate fixed the problem.

Figure 83

4.14 – Save the form

We can now save our form by clicking File > Save from the main menu. We are going to save our form to the same location that we saved our Word document. This author named the file HappyBirthdayForm_one.xsn.

Note: Do not end the name of the file in a number. Problems can arise since SharePoint can add numbers to the file name under certain conditions.

4.15 – Publish the form

Page 68: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 68 of 108

We now need to publish our form. Click on File > Publish. The publishing wizard will appear. On the first Wizard dialog, we select the radio button To a Network Location. We then browse to the same location we stored our Word document. This author named this file HappyBirthdayForm_one_Published.xsn. Click out the wizard by taking the defaults that are presented.

Note: The published .xsn file we create will be imported info Visual Studio later in this document. It will then be deployed as a feature where is will show up in Central Administration under Manage Form Templates automatically.

4.16 – Copy the ID of the form for use in Visual Studio.

We will need to enter the form ID in the workflow.xml file in Visual Studio since Visual Studio deployment will include our form as a feature. So, let’s copy the ID to the clipboard now. Click File > Properties as shown in Figure 84.

Figure 84

As shown in figure 85, copy the ID to the clipboard (and then to NotePad and save it). We will be pasting it into the workflow.xml file in Visual Studio when the time comes.

Page 69: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 69 of 108

Figure 85 – We will need the ID of the form in Visual Studio

Our form is now finished. We can now close the InfoPath application.

Page 70: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 70 of 108

STEP 5 – CODE OUR WORKFLOW IN VISUAL STUDIO

We can now turn our attention to our workflow project in Visual Studio 2008.

5.1 Create the project

Click on File > New > Project as shown in Figure 86.

Figure 86

Select the SharePoint 2007 Sequential Workflow as shown in Figure 87.

Page 71: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 71 of 108

Figure 87

As shown in Figure 88, configure the local site to where the workflow will be used. In this author’s case, it was his Team Site.

Page 72: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 72 of 108

Figure 88 – The author chose his Team Site to use for debugging

Page 73: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 73 of 108

As shown in Figure 89, select Happy Birthday Card Library from the dropdown list titled Library or List.

Figure 89

As shown in Figure 90, make sure the checkboxes appear as shown. We need to have the workflow started by either of the two means denoted by the check boxes. Click Finish and our workflow project is created.

Page 74: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 74 of 108

Figure 90

5.2 – Add activity components from the Toolbox onto the design surface

We now need to drag some of the workflow components from the toolbox onto the design view. We are going to create a task with a content type, so we need to drag CreateTaskWithContent type object onto our design view. Drag the other objects onto the design view until we have a design view that looks like Figure 91.

Page 75: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 75 of 108

Figure 91

Note: Each box on the form represents an activity. Blue activities are method activities and green activities are event handler activities.

5.3 – Add correlation tokens to our activities on the design view

We now need to set our correlation tokens for all the objects on the form.

Note on correlation tokens: Each blue and green box (a.k.a activity) on the design view must have a correlation token property set. The important point is that the correlation token for the OnWorkFlowActivated activity must NOT be the same as the other activities on the form (be they blue or green). So, when we set our correlation tokens, we will create a new correlation token name for all the activities OTHER than the OnWorkFlowActivated activity.

To set a correlation token for each activity, we right click on it, and select Properties from the drop down menu as shown in Figure 92. The procedure is the same for all the activities with the only difference being the name of the token we will enter. We will therefore have two tokens in play:

1. The OnWorkFlowCreated activity has a default correlation token name of workflowToken. We will accept this default.

2. We will create a new correlation token that will be used in every other activity. We will name that correlation token mainToken.

Page 76: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 76 of 108

Figure 92 – Right clicking on an activity to get the corresponding properties box

In the properties window for each of the activities (other than onWorkflowActivated1), we will type in the name mainToken. Figure 93 and 94 show the results. Note that we need to type (or cut and paste) in the name mainToken four times, once for each activity below onWorkflowActivated1.

Page 77: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 77 of 108

Figure 93 – workflowToken is unique to onWorkflowActivated1

Figure 94 – All other activities use mainToken as the name

Page 78: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 78 of 108

5.4 – Assign a task ID to createTaskWithContentType as a GUID (Globally Unique Identifier).

We now add a task ID property to the createTaskWithContentType activity. To get the GUID in Visual Studio, click Tools > Create Guid as shown in Figure 95.

Note: If your Visual Studio 2008 does not show the Create GUID menu item as shown in Figure 95, refer to Appendix B on how to get it to show up on the menu.

Figure 95

Click the radio button as shown in Figure 96 and click Copy. Then paste the GUID into the taskId property as shown in Figure 97.

Page 79: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 79 of 108

Figure 96

Figure 97

Page 80: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 80 of 108

5.5 – Assign the GUID from Figure 97 to the bottom 3 activities in the design view

The procedure we denote here will be repeated three times: one for each of the remaining activities (E.g. onTaskCreated1, onTaskchanged1 and completeTask1).

As shown in Figure 98, click on the ellipsis adjacent to the TaskId property for onTask1created.

Page 81: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 81 of 108

Figure 98

On the resulting dialog under the tab Bind to an Existing member, under createTaskWithContentType1, click on TaskId. Refer to Figure 99.

Page 82: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 82 of 108

Figure 99

Click OK, and the TaskId will now be associated with the taskId GUID from createTaskWithContentType1. Repeat this process for the remaining two activities.

5.6 – Create a rule for the whileActivity1

So, when the flow gets to the whileActivity1 activity box, what will cause the while loop to exit? At this point, we have to configure the activity to exit by means of a rule. The rule we will use is to exit when the value of a variable (which we will create in a moment) changes from false to true. The variable must be created in the C# code behind and we will name the variable _taskCompleted. Refer to Figure 100 which shows that we added C# code for the variable.

Page 83: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 83 of 108

Figure 100 – we added a new variable called _taskCompleted (defaults to false)

Now we can set the rule for the while activity. As shown in the property pane for whileActivity1, click on the dropdown and click on Declarative Rule Condition.

Figure 101

Then, type in the name whileCondition1in the ConditionName field and then click on the resulting ellipsis as shown in Figure 102.

Page 84: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 84 of 108

Figure 102 – Add the name, then click the elipses

In the resulting dialog box, type in !_taskCompleted for the condition as shown in Figure 103. Then click OK.

Figure 103

5.7 – Try a build: it should be successful

At this point, try building the solution. You should get a successful build with no errors.

5.8 – Add method stubs for the five activities in the design view

Now we need to add the method stubs that we will add code to in the code behind. For each of the activities, double click on each activity in design view. This will cause the stubs to be created for us behind the scenes as shown in Figure 104.

Page 85: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 85 of 108

Figure 104 – an empty stub created for all five activities

5.9 – Add the code from Appendix C to the stubs.

The entire code for the workflow is shown in Appendix C. You can cut and paste the code into your solution. At this point, we will discuss the code blocks in turn.

5.9.1 - onWorkflowActivated1_Invoked

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

In the code created for us by Microsoft, we see that the workflowId is assigned a default GUID when the variable id declared. We really want that workflowID to be assigned to the same value as the workflowPropertiesId.

Page 86: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 86 of 108

5.9.2 – createTaskWithContentType1_MethodInvoking

Figure 105

This function is called when the task with content type is created. Here we want to retrieve the Happy Birthday Card Word document from the workflowProperties list. It should be noted that there is only one item on the list since we have only 1 document in play at this time (E.g. our Happy Birthday Card document). Recall that the creator of the card typed in the Assigned To Login Name property in the Word document. We need to extract that name here and assign the name to a person who must perform the workflow task. We see that done on line 52. Once we have the assigned to name, we can create the SPWorkflowTaskProperties object required by the workflow. This is done on line 54. By specifying the person assigned to the task, the task to sign the birthday card will show up on that persons Task List in SharePoint.

Page 87: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 87 of 108

5.9.3 – onTaskChanged1_Invoked

Figure 106

This function is called when the task changed event fires. For our workflow, this event is fired when the signer of the card submits the InfoPath form we created. This function contains the main code for the workflow.

Lines 92 and 93 fetch the From and Message strings from the InfoPath form. Note that we have to cast the ExternalDataEventArgs to SPTaskServiceEventArgs to get at these two fields. Next, on line 98, we try to find our Happy Birthday Card Word document as a SPListItem object. Recall that we need to populate two fields on the Happy Birthday Card Word document that were left blank by the creator of the card. The two fields are From and Message (which we just got from the InfoPath form on line 92 and 93). So, we assign those fields to the birthday card on lines 108 and 109.

Now, since the task is completed by the signer, we also set the Completed field in the Word document as well on line 110. Note that this has nothing to do with the Completed text box in the InfoPath form. The explanation of how the Completed text box works to disable the Submit button in the InfoPath form is given in Appendix D.

Note that we set the _taskCompleted variable to true on line 111. Recall we set the while loop condition so that the while loop exits when this value becomes true. This is a critical line of code.

Page 88: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 88 of 108

5.9.4 – completeTask1_MethodInvoking

Figure 107

This function is called when the while loop exits. All we want to do here is to start the process of emailing our Happy Birthday Card to the intended recipient. So, we simply loop through the items in the library (there is only one in this example) and find our word document. Recall that the missing fields were populated in Figure 106. When we find the document, we pass it to our SendEmail() function.

Page 89: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 89 of 108

5.9.5 – SendEmail

Figure 108

This function is used to send the Word Happy Birthday Card to the intended recipient. Note that our Word document is passed to this function as a SPListItem item, not a Word document object. Also, notice on line 197 that we obtain the reply to email address from SharePoint. We configured this in Central Administration > Operations > Outgoing email Settings as shown in Figure 109. Also, notice on line 199 that we specify the mail server to be that configured in SharePoint. In figure 109, that main server is the Outbound SMTP Server, smtp.live.com (which is the mail server for hotmail). The issue with using Hotmail as the mail server is that the hotmail mail server is locked down to prevent spam. So, to use it, you have to provide authentication. The authentication credentials are your hotmail username and password. To provide these credentials, we use the NetworkCredentials object (which is also used with many other things in .NET such as web service proxy authentication). Also note that we are specifying to use SSL on line 205.

Page 90: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 90 of 108

Figure 109

Page 91: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 91 of 108

5.9.6 – LogToEventLog

Figure 110

To provide logging to the Windows event log, we create our own log named HBEventLog. We navigate to the event log in Windows 2003 by clicking Start > Administrative Tools > Event Viewer. Our log is shown in Figure 111.

Figure 111

This concludes the discussion of the C# code.

Page 92: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 92 of 108

STEP 6 – CONFIGURE WORKFLOW.XML AND FEATURE.XML IN VISUAL STUDIO

So, what is the mechanism by which our InfoPath form is deployed, and what is the mechanism which causes it to be displayed in a SharePoint web page when the signer of the birthday card clicks on the task Please sign this birthday card? (See Figure 6). The answer is in the files workflow.xml and feature.xml. Refer to Figure 112 which shows our Visual Studio project.

Figure 112

There are 3 main steps required for the InfoPath form configuration. They are:

1. Include the InfoPath form in the Visual Studio Project2. Configure the file workflow.xml3. Configure the file feature.cml

6.1 – Include the InfoPath form in the Visual Studio Project

The first thing to notice is that we have included our InfoPath form .xsn file in the project. The name is HappyBirthdayForm_one_Published_deployed.xsn. This form will be deployed as a feature when we click on the Build > Deploy HBWorkflow in Visual Studio. However, we will need to perform steps 2 and 3 for this to happen.

Page 93: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 93 of 108

The important thing here is that we include the .xsn file in the project. Recall from 4.15 that we published our .xsn file to a directory on disk. Simply include that file in the Visual Studio project (right click HBWorkflow > Add > Existing Item).

6.2 - Configure the file workflow.xml

Appendix E has the code for the workflow.xml file as does Figure 113.

Figure 113

There are 2 lines of interest here. They are lines 11 and 15.

Line 11 - We added line 11 with the hexadecimal number as shown. TaskListContentTypeId needs to be set to the value for your task type. If you do not use a custom task list defined in a content type, you can use the value 0x01080100C9C9515DE4E24001905074F980F93160 as shown. In our case, we do not use a custom task list so this number will be used as shown.

Line 15 – Remember when we copied our InfoPath form ID to the clipboard in Figure 85? That is the ID code we put on this line. The other thing to note is the name of the xml tag we place it in. The tag is <Task0_FormURN> and this tag denotes what form should be displayed for the first Task in our sequential work flow (note the character ‘0’). In our case, the first task is defined in the blue box createTaskWithContentType1 in design view. In our case we only have one task, so the Xml tag will be <Task0_FormURN> . What if we had a 2nd task object in design view and wanted a different InfoPath form to be displayed for that task? Well, we would define a new Xml tag <Task1_FormURN>. Notice that we incremented the number by 1. So, for every task in design view for which we need to show an InfoPath form, we add an XML tag but increment the number by 1. This is actually explained in the notes in the default Workflow.xml, but we have removed those notes for brevity.

6.3 - Configure the file feature.xml

The feature.xml file code is in Appendix F and in Figure 114. The key line here is line 13.

Page 94: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 94 of 108

Line 13 specifies the .xsn file that should be deployed as a feature. When we deploy the project using the Visual Studio deployment menu item, the InfoPath form will be installed as a feature for us. Additionally, it will show up in Central Adminstration > Application Management > ManageFormTemplates as shown in Figure 115. We can verify this by going to c:\program files\common files\microsoft shared\web server extensions\12\TEMPLATE\FEATURES\HBWorkflow and seeing the .xsn file there after the deployment takes place. See Figure 116.

Figure 114

Figure 115

Page 95: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 95 of 108

Figure 116

CONCLUSION

We now have all the pieces in place. You can debug the program, or simply run it. Visual Studio will deploy the project each time you debug, so you don’t have to perform a 2 step process of build and deploy. Also, you should be able to exercise the program as denoted in the Figures at the beginning of this tutorial.

Hopefully, students of this tutorial will find this tutorial helpful in understanding some of the things we went over in class. Also, feedback is encouraged.

END DOCUMENT

APPENDICES FOLLOW

Page 96: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 96 of 108

APPENDIX A

Figure

Note: On the resulting page shown in Figure, the Content Types section is shown. If it does not show on your screen, you need to click Advanced Settings on the page and in the resulting page click on the Yes radio button for Allow management of content types as shown in Figure

Figure

Page 97: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 97 of 108

APPENDIX B

Display Create GUID on Visual Studio 2008 Tools menu.

1. Choose the Tools -> External Tools...2. Click the Browse (…) button and find the guidgen.exe in the C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\ folder.

3. Click the OK button.

Page 98: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 98 of 108

APPENDIX C#region usingusing System;using System.Diagnostics;using System.Net;using System.Net.Mail;using System.Workflow.Activities;using Microsoft.SharePoint;using Microsoft.SharePoint.Workflow;using System.Reflection;#endregion

namespace HBWorkFlow{ public sealed partial class Workflow1 : SequentialWorkflowActivity { #region Declarations private const string _formatedErrorMsg = "{0} : {1}"; private const string _errorTitle = "Happy Birthday Workflow : "; private bool _taskCompleted; public Guid workflowId = default(Guid); public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties(); #endregion

#region Constructor /// <summary> /// Default Constructor /// </summary> public Workflow1() { InitializeComponent(); } #endregion

#region createTaskWithContentType1_MethodInvoking /// <summary> /// Event handler called when createTaskWithContentType /// event is triggered. /// </summary> private void createTaskWithContentType1_MethodInvoking(object sender, EventArgs e) {

SPListItem birthdayCardWordDocument = null;

try { SPList list = workflowProperties.List; foreach (SPListItem item in list.Items) if (item.Name.ToUpper().Equals("HAPPY BIRTHDAY.DOCX")) { //Address hard coding this later on birthdayCardWordDocument = item; break; }

Page 99: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 99 of 108

if (birthdayCardWordDocument == null) throw new SPException("Could not find Word document named 'Happy Birthday.docx' on the list in the library. Unable to proceed.");

string assignedTo = birthdayCardWordDocument.Properties["Assigned To Login Name"] as string;

createTaskWithContentType1.TaskProperties = new SPWorkflowTaskProperties { AssignedTo = assignedTo, Title = "Please sign this birthday card!", Description = "InfoPath form presented to a signer of a Birthday Card", DueDate = DateTime.Now.AddDays(7) };

} catch (Exception ex){ LogToEventLog(_errorTitle, String.Format(_formatedErrorMsg, MethodBase.GetCurrentMethod(), ex.Message), EventLogEntryType.Error); } } #endregion

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

#region onTaskChanged1_Invoked /// <summary> /// Event handler called when task is changed. This will occur /// when the user submits our InfoPath form. /// </summary> private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e){

try{ SPListItem birthdayCardWordDocument = null; string from = ((SPTaskServiceEventArgs)e).afterProperties.ExtendedProperties["From"] as string; string message = ((SPTaskServiceEventArgs)e).afterProperties.ExtendedProperties["Message"] as string;

if (String.IsNullOrEmpty(from) || String.IsNullOrEmpty(message)) throw new Exception(" From extended property was null and/or Message extended property was null.");

Page 100: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 100 of 108

SPList list = workflowProperties.List; foreach (SPListItem item in list.Items) if (item.Name.ToUpper().Equals("HAPPY BIRTHDAY.DOCX")){ birthdayCardWordDocument = item; break; }

if (birthdayCardWordDocument == null) throw new Exception(" Birthday Card Word document list item was null.");

birthdayCardWordDocument.Properties["From"] = from; birthdayCardWordDocument.Properties["Message"] = message; birthdayCardWordDocument.Properties["Completed"] = "Completed"; _taskCompleted = true;

birthdayCardWordDocument.SystemUpdate(); } catch (Exception ex){ LogToEventLog(_errorTitle, String.Format(_formatedErrorMsg, MethodBase.GetCurrentMethod(), ex.Message), EventLogEntryType.Error); } }

#endregion

#region LogToEventLog /// <summary> /// Our function to log to the Windows Event log /// </summary> /// <param name="errorTitle">The title to be applied to the /// error entry.</param> /// <param name="message">The message to appear in the event log.</param> /// <param name="msgType">The message type (E.g. Error, information, etc.</param> public static void LogToEventLog(string errorTitle, string message, EventLogEntryType msgType){

EventLog hblog;

try{ if (!EventLog.SourceExists("HBEventLogSource")) EventLog.CreateEventSource("HBEventLogSource", "HBEventLog"); using (hblog = new EventLog { Source = "HBEventLogSource" }) hblog.WriteEntry(errorTitle + " : " + message + " : " + msgType); } catch { } } #endregion

Page 101: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 101 of 108

#region completeTask1_MethodInvoking /// <summary> /// Event handler called when the completeTask event is fired. /// </summary> private void completeTask1_MethodInvoking(object sender, EventArgs e){

SPListItem happyBirthdayWordDocument = null;

try{ SPList list = workflowProperties.List; foreach (SPListItem item in list.Items) if (item.Name.ToUpper().Equals("HAPPY BIRTHDAY.DOCX")){ //Address hard coding this later on. happyBirthdayWordDocument = item; break; } SendEmail(happyBirthdayWordDocument); } catch (Exception ex){ LogToEventLog(_errorTitle, String.Format(_formatedErrorMsg, MethodBase.GetCurrentMethod(), ex.Message), EventLogEntryType.Error); }

}

#endregion

#region SendEmail /// <summary> /// Function used to send the Happy Birthday Card Word document /// as an attachment. /// </summary> /// <param name="happyBirthdayWordDocument">Our Birthday Card as a SPListItem.</param> private void SendEmail(SPListItem happyBirthdayWordDocument) {

#region Programmers Notes //This author has SharePoint configured to use Microsoft Hotmail //as the outgoing mail server (E.g. smtp.live.com as the hotmail outgoing mail server). //This is set in Central Administration/Operations. //This mail server has security in place such as SSL and is currently requiring authorization. //We supply the authorization by means of a NetworkCredentials object. You will have to have an //account with the mail service you use so that you can supply your own credentials. #endregion

try { string toAddress = happyBirthdayWordDocument.Properties["Email address"] as string; const string subject = "A Birthday Card For You!";

Page 102: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 102 of 108

const string messageText = "Please open the attached Birthday Card!"; SPWeb web = workflowProperties.Web; string replyTo = web.Site.WebApplication.OutboundMailReplyToAddress; MailMessage mailMessage = new MailMessage(replyTo, toAddress, subject, messageText) { IsBodyHtml = false }; string smtpAddress = web.Site.WebApplication.OutboundMailServiceInstance.Server.Address; SPFile attachmentFile = happyBirthdayWordDocument.File; Attachment attachment = new Attachment(happyBirthdayWordDocument.File.OpenBinaryStream(), attachmentFile.Name); mailMessage.Attachments.Add(attachment); SmtpClient smtp = new SmtpClient(smtpAddress) { EnableSsl = true, UseDefaultCredentials = false,

Credentials = new NetworkCredential("[email protected]", "yourpassword")

}; smtp.Send(mailMessage); } catch (Exception ex) { LogToEventLog(_errorTitle, String.Format(_formatedErrorMsg, MethodBase.GetCurrentMethod(), ex.Message), EventLogEntryType.Error); } }

#endregion

}}

Page 103: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 103 of 108

APPENDIX D – InfoPath form feedback

This appendix will attempt to describe the mechanism by which the submit button on the InfoPath 2007 form is disabled after the workflow completes.

Recall that in Figure 61, we specified that the button should be disabled whenever the text in the Completed text box is set to the number “1”. Nowhere in our code do we see that we as programmers have set this value. In fact, the default value of “0” in the text box when the form is loaded does not come from our C# code either.

In the topic 4.11 – Configure the form to receive data from the workflow on load, we specified a secondary data source to receive data from the host whenever the InfoPath form loads. We also specified that the ItemMetaData.xml file be used as the secondary data source on receive. If we exercise the sending of the Happy Birthday Card workflow, we see that the InfoPath form contains a value of “0” on first load. However, when the form is submitted, invoking the form a 2nd time shows the value has been set to “1”. Again, we as programmers had nothing to do with these values appearing in the text box.

This happens because we use the name ows_Completed in the Xml file and reference it in the properties of the Completed text box on the form as shown in Figure A1. This tag appears to be linked to a Boolean value denoting whether or not the task is in the completed state. This goes on behind the scenes and appears to be an undocumented feature from Microsoft.

Page 104: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 104 of 108

Figure A1

If we tried to substitute a different ows_ value, such as ows_Done (or other name of your choice), then the mechanism will not work, mainly because we cannot set the value to “1” in the C# code behind after the task completes. The key point here is that we would need to set the value after the task completes, but that is too late in the flow to change it.

As an alternative, if we were to attempt to set a value in the Completed text box before the task completes, say in the createTaskWithContentTpe1_MethodInvoking event handler, then it would work. The value “1” would appear in the InfoPath form. However, the user would be helpless since he/she could not submit the form since the submit button would be disabled on first load! The form is dead from the outset. Not good. We want the “1” to appear on the subsequent loads, but again, that is after the task is completed.

To set the value of the form on first load (which is useless for us as mentioned above) would require that we include a new property in our C# code called createTaskWithContentType1_TaskProperties since that would give us access to the extendedProperties object. Our code would look like Figures A2 and A3.

So, where does this leave us to disable the submit button after the task completes? Well, we must use the undocumented feature where the Boolean value of “0” and “1” is

Page 105: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 105 of 108

provided for us by using ows_Completed as the name in the ItemMetaData.xml file and specified in the binding for the Completed form.

It would be great if readers of this tutorial could research this further and find documentation on this phenomenon.

Page 106: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 106 of 108

Figure A2

Figure A3 – This line would set the value in the InfoPath form on 1st load.

Page 107: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 107 of 108

APPENDIX E – workflow.xml

<?xml version="1.0" encoding="utf-8" ?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/"><Workflow Name="HBWorkFlow" Description="My SharePoint Workflow" Id="68cfd787-087f-4baf-8718-00666bd6afd4" CodeBesideClass="HBWorkFlow.Workflow1" CodeBesideAssembly="HBWorkFlow, Version=1.0.0.0, Culture=neutral,

PublicKeyToken=c588e451cdda9911" TaskListContentTypeId="0x01080100C9C9515DE4E24001905074F980F93160">

<Categories/><MetaData>

<Task0_FormURN>urn:schemas-microsoft-com:office:infopath:HappyBirthdayForm-one-Published-deployed:-myXSD-2009-09-15T14-10-01</Task0_FormURN>

<StatusPageUrl>_layouts/WrkStat.aspx</StatusPageUrl></MetaData>

</Workflow></Elements>

Page 108: Tutorial Share Point Happy Birthday Workflow Slideshare

Page 108 of 108

APPENDIX F – Feature.xml

<?xml version="1.0" encoding="utf-8" ?>

<Feature Id="648c9208-3138-4bf3-acd4-06b7e5e51b11" Title="HBWorkFlow 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="HappyBirthdayForm_one_Published_deployed.xsn"/> </ElementManifests> <Properties> <Property Key="GloballyAvailable" Value="true" /> <Property Key="RegisterForms" Value="*.xsn" /> </Properties></Feature>