My last trick in this three part series (part 1, part 2) is how to leverage a custom InfoPath form within your task modification pages. Whenever working with workflows and the task management framework, it is a much more elegant to use InfoPath forms rather than the out of box SharePoint forms. See below:
Out of box task edit form:
Custom InfoPath Form (Anything you want!):
Other than task forms, just like how SharePoint Designer can generate initiation forms and status forms, you can also leverage your own forms for them as well with Visual Studio workflows. Now rather than build a workflow from scratch I'm going to extend the workflow built in the second part of this series, and add to that workflow another form and some more activities.
The first thing we need to do to the workflow we created in the last post is edit the Feature.xml and Elements.xml files. We need to specify to the feature/workflow that we are going to use custom edit forms rather than the out of box form. Make these additions to the Feature.xml file:
<?xml version="1.0" encoding="utf-8"?>
<Feature Id="[Guid]"
Title="Expense Report Workflow"
Description="desc."
Version="1.0.0.0"
Scope="Site"
ReceiverAssembly="Microsoft.Office.Workflow.Feature, Version=12.0.0.0, Culture=neutral, PublicKeyToken=[Token]"
ReceiverClass="Microsoft.Office.Workflow.Feature.WorkflowFeatureReceiver"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="Elements.xml" />
</ElementManifests>
<Properties>
<Property Key="GloballyAvailable" Value="true" />
<Property Key="RegisterForms" Value="Forms\*.xsn" />
</Properties>
</Feature>
Adding the receiver will allow us to deploy a form into InfoPath Forms Services when the feature is installed. The properties specify where our form is located that the feature needs to deploy.
Next, add these updates to the Elements.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Workflow
Name="Expense Report Workflow"
Description="desc."
Id="[Guid]"
CodeBesideClass="TestInfoPathWorkflow.Workflow1"
CodeBesideAssembly="TestInfoPathWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[Token]"
TaskListContentTypeId="0x01080100C9C9515DE4E24001905074F980F93160"
ModificationUrl="_layouts/ModWrkflIP.aspx"
>
<MetaData>
<Task0_FormURN>urn:schemas-microsoft-com:office:infopath:EditForm-xsn:-myXSD-2009-02-21T03-35-27</Task0_FormURN>
</MetaData>
</Workflow>
</Elements>
The TaskListContentTypeId specifies what the Task content type you're leveraging. The content type I have specified above is the default, out of box content type for task, but if you've built your own, you'd enter it here. The ModificationUrl tag points to an aspx page that is deployed when you install MOSS, and this page hosts and renders the InfoPath form. The metadata Task0_FormURN tag holds the unique ID that is given out form when it is uploaded into Forms Server. This essentially tells the workflow which form to load in the ModWrkflIP.aspx page.
Next add two more activities onto the workflow1.cs designer surface. Add a CreateTask and OnTaskChanged activities. After you drop the activities onto the surface, you'll see a red exclamation point. This is because these activities need to a correlation token. Make sure you give the new activities the same token (can be any text you want), but make it a different token from the other activities:
The reason they need to be different is a token is needed for every list the workflow interacts with. In our case, we have two lists, the workflow origination (host) list, and a tasks list.
Essentially, my workflow above will wait for the form to be edited (part 2 of the series), and after it is edited it will create a new task in a tasks list and then wait for that task to be edited. To get the create task activity to work; we need to wire up a few things. First, in the code behind add the following properties at the top of the class:
public Guid taskId = Guid.NewGuid();
public SPWorkflowTaskProperties properties = new SPWorkflowTaskProperties();
Then, the two new activities need to point to these fields. Go to the properties of both activities and on the TaskId property, click the "…" box:
Choose the tasked field that was just added, and click ok:
Do the same for the TaskProperties property, but point it the the "properties" field.
The last thing to do is add some code into the event handler of the CreateTask. Right click the CreateTask activity and choose Generate Handlers and add the following code into the method that was generated:
properties.TaskType = 0;
properties.Title = "HI!";
The TaskType property corresponds to the TaskForm0_URN piece of Meta-Data that was added to the Elements.xml file. The "0" after "Form" is the TaskType. This is needed because you may want to have multiple forms for each task type. For instance, if you drop several tasks assigned to different people, the person's role may be different which may necessitate is different form for that person. The TaskFormX_URN distinguishes which form you want to loaded for which task type (person).
Other than TaskType, you can set all kinds of task properties like Title, AssignedTo, Status, etc. These values will get stuffed into the new task that is created. After this, we're ready to BUILD the project and update the assembly in the GAC (c:\windows\assembly). However, we also need to get our feature updated in the 12 Hive, Features directory. Copy the Feature.xml and Elements.xml files to the feature folder they were deployed to originally (post 2 of the series). The only other step before we restart IIS is to drop the form we want loaded in a "Forms" folder within the feature's folder.
Remember the "RegisterForms" property that was added to the Feature.xml file? This property tells the feature where the form that will be leveraged in the workflow resides, so the form can get deployed to Forms Server. Notice the value is "Forms\*.xsn". This means that within the feature's directory, there is a folder called Forms, and all those forms need to get loaded into Form Server. Create this directory and copy your InfoPath form into it:
Now this feature will need to be Installed (uninstalled first if updating an existing) to get the form deployed to Form Server. Run the STSADM InstallFeature command to do this (IISRESET beforehand!). Thereafter, you should see your form in Form Server:
One thing to note, the "Workflow Enabled" column MUST be YES for this to work. Yes means that the form was added to Form Server via a feature workflow, and if it is "No", the form was added manually. Manually added forms will not work! J took me a while to figure this out…
Ok! The assembly and feature have been updated, the task edit form we're using has been deployed, now it's time to start the workflow which will create a task in a task list, and when that task is edited, our custom form will load instead of the out of box SharePoint form. Sweet!
Phil