In this blog, I will show how to create an InfoPath form that is used by a sequential workflow to capture data as a task to an end user. The workflow we are creating is kicked off OnCreate on a custom list. I won’t get into the details of the list and all the functionality unless it is relevant to what we are trying to demonstrate here. What is important is understanding the basic flow. An item is created on a list, the workflow assigns a task to a user. The task is to provide a score sheet evaluating the data put into the list. We will use an InfoPath 2007 form to capture that data and push the data on submit back to the originating list, not to the task list. Then the workflow can continue on to carry out the rest of the actions necessary.
I started by creating the InfoPath form needed to capture the data that I want pushed back into the list. I am using Visual Studio 2008 to build both the InfoPath form and the workflow. I am using VS2008 rather than VS2010 in order to take advantage of building the InfoPath form in the same solution. This makes it easier to debug. Otherwise, I would definitely recommend using VS2010 instead. (Maybe the subject of another blog )
You can see from this form, we are capturing very different from a traditional task. We are going to switch to talking about the workflow. Now that we have the InfoPath form created, we need to create the stub for the submit and give a way to cancel. Add two buttons, one for Submit and one for Cancel. On the cancel button, simply go to the button properties, click on rules, Add, Add Action and select Close the form:
For the Submit button it is a little different. We need some code behind to take the data provided by the user and push it back to the list item that originated the workflow. So, right click on the button and select properties. This time, instead of selecting rules, pull down on the Action field and select Submit. The button is now a “known” submit button. Click on Submit Options. I like the form to close after the user has submitted, so click on the Advanced button and check Allow users to submit this form. Then in the after submit field, select the Close the form option. Then click the radio button setting the button to Perform custom action using Code. It should look like the following:
Now click on the Edit Code button and it will take you to the code behind in a stubbed out method. This is where you will add code to handle the actual submission. Prior to that though, we need to set some more things up. So, we’ll come back to this. Let’s create the task and then come back to the InfoPath form code.
In my workflow, I added a CreateTask action:
Then I set up the TaskProperties and TaskId in the createTask1 properties:
Now, let’s get into the code to set the properties for the task being generated. Double click on the createTask1 activity on the workflow designer. This will generate the stub for the invoking method on this activity. From here, we set the TaskId, the fields that need to be populated like Assigned To, Title, DueDate, etc. And then, because we want the InfoPath form to be used instead of the traditional Task form, we tell the task that its task type is 1. I’ll explain this in more detail later on; for now just understand that using the default task form would have a task type = 0, other values point to other forms. We will also need to know the list id from the item that initiated the workflow. We achieve this by pushing the id into an extended property called “ItemId” that we created on the Tasks list. Let’s take a look at the code:
Now, let’s get back to the InfoPath code. We need to push data back to a SharePoint list, so make sure that you have a reference to the SharePoint dll. Simply add reference, browse to it by going to C:\Program Files\Common Files\microsoft shared\Web Server Extensions\12\ISAPI and selecting Microsoft.SharePoint.dll. Now we need to get to the OnLoading event on the InfoPath form. To do this, in Visual Studio while looking at the code behind for the InfoPath form, click on the menu item Insert and select Loading Event from the fly-out menu:
That gives you the stub for the loading event on the form. In this event we need to capture the TaskId and the originating ListItemId and push them into FormState. We need this information later in order to push data into the appropriate places. Here’s the code:
Ok. So now we need to handle the submission of the InfoPath form. Since we captured the necessary information to reach back to the list items in the FormState, everything is fairly straightforward.
Couple of last things. We need to modify the feature.xml and workflow.xml in the workflow. In the feature.xml in the ElementManifests element, we added the element <ElementFile Location=”ProposalScoreSheet.xsn” />. Save it.
In workflow.xml, we do a little more. You need to open the form that you just designed in InfoPath in design mode. Then go to File –> Properties and copy the URN generated for the form. There may be an easier way to get this value, but I don’t know it. Then, in the xml in the MetaData element, add an element like: <Task1_FormURN>urn:schemas-microsoft-com:office:infopath:ProposalScoreSheet:-myXSD-2011-06-10T14-03-34</Task1_FormURN> substituting in the urn that you just copied for the one that I have here.
Then, in the Workflow element, under name, description, id, CodeBesideClass, CodeBesideAssembly you need to add the following line: TaskListContentTypeId=”0x01080100C9C9515DE4E24001905074F980F93160″> making sure that you don’t end up with an extra “>”. Save it.
Last thing, you need to create your install.bat to push everything to SharePoint properly. Here is a copy of my install.bat to see how I do my install:
After writing this all, I ran my code. I have an error somewhere and it is a weird one. Rather than delete this for now, I’ll just leave this warning and continue troubleshooting offline. When I find it, I’ll fix the blog. In the mean time, beware of what I have written!