OK Everyone! This guide has now been re-written for MOSS 2007 RTM! There aren't too many changes but the new 'how-to' includes a lot more images and hopefully better explanations:
http://weblog.vb-tech.com/nick/archive/2007/02/25/2207.aspx
I'm leaving this page up here for historical purposes! :-)
========================================================
Ok, I’ve given in and am going to write it! I thought someone else would have written the definitive howto by now but from a search on Google it doesn’t look like they have. The only posts I have found are from people having problems trying to create and deploy the HelloWorld type workflow with Visual Studio 2005. This is going to be a long post, so hold on. Some of it will be a re-write of the MSDN walk through here. The reason I’m doing it again is because I found the MSDN article hard to read and understand, plus I think there were a few errors in it. Also we’ll be creating this workflow in a slightly different order. Some of the screen shots I’ve added in to help explain things have been shrunk. To get a full view just click on them.
One final note of warning. This was coded on a Windows 2003 virtual machine with Visual Studio installed directly on it. MOSS 2007 basic installation was also put on which was the beta 2 version. Any changes for beta2 tr and I’ll try to update you. Ok, here’s the first step:
1, Download and install the Beta 2 ECM starter kit. This installs some workflow examples for you, but more importantly the Visual Studio 2005 (VS2005) templates for creating SharePoint sequential and parallel workflows. Once the starter kit is installed start VS2005 and you should see the templates in the project type menus.

2, Lets just talk about the workflow we are going to create. We want to allow our workflow to be associated with a list or document library. When a document is created or changed (this is a setting chosen upon binding the workflow to the list/library), a person specified will have a task created for them, with some pre-defined instructions and comments. When clicking the task the user will have a designed form where they will have instructions present, and can decide whether to complete the task with a checkbox.
From the above we’re going to need 2 InfoPath forms. Number 1 is used when binding our workflow to a list/library where we’ll enter the user who’ll get the task, and a few instructions and a comment. The second form is when the user clicks on the task. In this form they can add comments and click a checkbox to complete the workflow.
3, So lets create our Visual Studio 2005 project. Open VS 2005 and select a SharePoint 2007 Sequential Workflow. Give your project an interesting name such as NicksWorkflow. In the solution explorer window you’ll see a number of files created for you:
Feature.xml – A workflow is basically a Feature. More on how we use this to deploy our workflow later.
Workflow.xml – Lists the seperate parts of the workflow to deploy with it, for example InfoPath forms
Workflow1.cs – The actual workflow components and code.
Install.bat – A helper batch program to deploy our workflow. We just need to edit it a little and then run it once we’ve written the workflow and created our forms.
For now though we’re going to leave VS and open InfoPath 2007 to create our two forms; DemoInitiation and DemoReview.
4, DemoInitiation
When binding a workflow to a list/library you get the standard first page:

The second page is then entirely upto how the workflow feature has been created. We’re going to create an input form that captures the user we want to check our document, a textbox where we can enter instructions to them, and a comments textbox. Upon opening InfoPath 2007
a, Select design a form template, and select Blank from the list of templates in the ‘Based on’ selector.
b, Create a html table with 3 rows and 2 columns
c, Drag and drop some labels, textboxes and a button on the form so it looks like this:

Rename the textboxes and submit button so they are the same as in the image above. Do this by double clicking on the control and bringing up the properties window.
d, We now want to give the forms fields (textboxes) collection a unique name. In the Design Tasks pane select the Data Source pane, then double click on myFields text, and type InitForm into the Name textbox of the properties form that opens up. Click OK and you’ll see the collection name in the Data Source pane update.
e, We now need to add some rules to our submit button so that it will get submitted to the SharePoint environment upon being clicked.
– double click the submit button to bring up the properties.
– on the general tab, click the Rules button, and then Add.
– click Add Action… and then choose ‘Submit using a data connection’ from the drop down. Then click Add… button.
– in the ‘Data Connection Wizzard’, leave ‘Create a new connection to:‘ and ‘Submit data’ selected and click Next.
– select ‘To the hosting environment, such as……..’ and click Next. Then click finish. Click Ok on the Action form.
– click Add Action… to add another action. This will be one to close the form once it’s submitted.
– Select ‘Close the Form’ from the drop down on the next form, making sure ‘If changes have not been saved, prompt user to save’ is not selected.
– Click OK to exit various boxes. The rules list for the submit button should now look as below:

f, Now we need to make sure our form can be hosted by forms server and so be served up in a browser. In the Design Tasks pane, select Design Checker. Click ‘Change compatibility settings…’ and then in the following properties form, check ‘Design a form template that can be opened in a browser or InfoPath’. Also enter the url of the server where you’ll be deploying the workflow to. I’m not entirely sure if this is necessary, but I’ve had trouble with forms where I haven’t put the server url in.

The final step is to do with language packs, and which ones you have installed on the server. In the same Properties windows where you set the compatibility settings, click on Browser in the listbox on the left, then in the Form Language drop down, pick one that has a language pack installed on the MOSS 2007 server. By default this will be English (U.S.). If you do not choose a language that is installed the forms will not be copied over and so will be unable to run.

g, Save the InfoPath form to somewhere such as My Documents. Call it ‘DemoInitiation’.
h, Publish the InfoPath form. File -> publish. Choose ‘To a network location’and click Next. On the next form, browse to where you created your VS 2005 workflow project and pick the same directory as workflow1.cs. Leave the filename as DemoInitiation.xsn. Click Next. Next again, publish, and then Close.
When we submit our forum to SharePoint we need to be able to get the data from the submitted form to be able to use in our workflow. To help do this we can generate a class using xsd.exe based off the form schema file.
a, First we need to save our InfoPath form as Source Files. File -> Save as Source Files. Browse to the location you want to save the file (such as My Documents), and click OK. By default the source files are saved as filename myschema.xsd. Once saved close InfoPath.
b, Open a VS 2005 command prompt and navigate to where you saved the source file. Then type:
xsd myschema.xsd /c
c, this generates a c# class file called myschema.cs. Rename the file to InitForm, and add it to you VS 2005 workflow project. If you take a look inside the classes code you’ll see the name of the class is the same that we gave to the forms field collection.

5, Task Edit Form.
The second form we need to create is one that show’s when we edit our task which is created as part of the workflow.
Open InfoPath 2007 again and create a blank form as we did before. On this form we’re going to want an instructions textbox where we’ll place the instructions entered when we bound the workflow to the list/library, a checkbox to check to say the workflow is complete, and an ok button. Lay it all out and rename the fields to something like below

Add the same rules to the OK button as you did to the submit button for the DemoInitiation form (ie submit to a hosted environment, and then close).
When this Edit form opens we’re going to want to pass some data to it (ie the instructions), we do this by creating a task schema and adding it as a secondary data source.
a, Open up notepad and add the following:
b, In this file we need to define every property that we are going to pass to the Task Edit form. To do this, add an attribute comprised of the prefix ows_ and the name of the task property. Set the attribute equal to an empty string. So to pass the instructions to the Task Edit form that were added when we bound the workflow to the list/library we add the following attribute:
ows_instruction=””
So your finished notepad text should be:

Please note that this is case sensitive. Save the file as ItemMetaData.xml (location doesn’t really matter).
c, Now we need to add the task schema to our Edit Task form as a secondary data source. Back in InfoPath, in the Design Tasks pane select Data Source, and then click Manage Data Connection. Click Add… in the following Data Connections Form. In the following Data Connection Wizzard select to ‘Create a new connection to:‘ and then ‘Receive data’, click Next. Select ‘XML document’ as the source of where to receive the data, then Next. Browse to the ItemMetaData.xml file you just created and saved and select it, Then Next. Select ‘Include the data as a resource file in the template’ and Next. The name for the data connection should be ItemMetaData, and make sure ‘Automatically retrieve data when form is opened’ is selected. Click Finish and close.

d, Now we need to bind our fields to the data source we just added.
– double click the instructions textbox
– In the Properties dialog box, on the Data tab, under Default Value, click the formula button.
– On the Insert Formula dialog box, click Insert a Field or Group.
– In the Select a Field or Group dialog box, select your ItemMetadata data connection from the drop down menu.
– Select the ows_MetaInfo_instructions element.
– Click OK. On the Insert Formula dialog box, click OK. On the Properties dialog box, click OK.

The instruction textbox is now set so that when the form loads, it will display the instructions previously set up when first initializing the workflow.
e, As with the DemoInitiation form, set this form so it is browser compatible, and again enter the url of your Forms Server to verify compatibility. Also make sure you set the browser language correctly.
f, Save the form to a location such as My Documents, and then publish it to the same directory as your workflow files, again as you did with the DemoInitiation form.
That’s it for InfoPath. Now we get to turn our attentions to VS 2005 and actually get coding our workflow.
6, Open up VS 2005 and load your DemoWorkflow project if you’ve closed it. Double click on Workflow1.cs and the workflow designer will show up. Anyone who’s being playing around with Windows Workflow Foundation will recognise that it’s exactly the same design environment. All we need to do before getting started is add the SharePoint workflow components to our toolbox. Right click on the toolbox, and click ‘Choose Items’. Because you created the project from a SharePoint Workflow template the right references have been added so we just need to select the controls to add. Click on the ‘Namespace’ column header to sort the controls by namespace and then scroll down till you find the controls with the namespace Microsoft.SharePoint.WorkflowActions. Select all these controls and add them in. As you’ll see from the image below this adds a ton of exciting new controls that are out of scope for this beginner article but I’m sure we’ll look at them all in detail in due time.

As you can see on the Workflow1.cs design surface it already creates the first workflow step for us with a onWorkFlowActivated action. This will always be the first Workflow action of any workflow. Below this action is an arrow and a kind of stop sign. We can drag and drop any new workflow actions from the tool box and place them on the arrow. Before we do that though there are a few properties we can check before we get going. If you go into the code view of workflow1.cs you’ll see
public sealed partial class Workflow1: SequentialWorkflowActivity
{
public Workflow1()
{
InitializeComponent();
}
public Guid workflowId = default(System.Guid);
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties workflowProperties = new Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties();
}
This is all created for you because you used a template project. If you view the properties of work onWorkflowActivated1 you’ll see the following important properties set for you:
CorrelationToken : workflowToken
OwnerActivityName : Workflow1
WorkflowId – expand this
Name : Workflow1
Path : workflowId – the name of the guid id that you can see above in the code created for us.
WorkflowProperties – expand this
Name : Workflow1
Path : workflowProperties – again this is a variable that was created for us and set from the code above.
We also get an event for this control. When this fires we’ll want to setup any initial variable values that are required for the workflow. Type into the Invoked space onWorkflowActivated and press enter. You’ll see it goes to the code view and creates our event handler for us with the correct interface. We’ll come back to this later.
Now to add our first workflow control. Now that the workflow has actually started the first thing we want to do is create a task for the person who’s been set to complete it. Remember we defined this when attaching the workflow to an actual list in SharePoint. To do this drag and drop a CreateTask control just below our onWorkflowActivated1 control.

We need to set a few properties for this control. First type in the Correlation Token as taskToken. Upon pressing enter you’ll see that you can expand this property to reveal OwnerActivityName which once again should be set as Workflow1.
Next we’ll set the TaskId and TaskProperties which can be accomplished in a couple of ways. First method is to click on the default value of TaskId (0000–0000…. or something) and you’ll see three ellipses on a button appear. Click on this and it’ll open a dialogue box for you. Click on the ‘Bind to a new member’ tab and enter taskId in the textbox below ‘New member name:‘ then click ok. You’ll see now that not only have 2 pairs of name and values gone into the TaskId property, but you can expand them out to set them seperately. Also if you switch to code view, you’ll see that a variable called taskId (the name we entered in the textbox) has been added to our code for us.

Follow the same procedure for TaskProperties, except in the ‘New member name:‘ textbox enter taskProps. Switch back to the code view again and you’ll see the variable created for us. If you go back to the createTask1 properties view and click the ellipses for TaskProperties again, you can see in the ‘Bind to an existing member’ that this property is bound to taskProps in our Workflow1 class. So as well as using this dialog box and the ‘Bind to a new member’ tab, we could have gone into our code view, created the taskId and taskProps variables ourselves, and then used the Bind to an existing member view to set the values of the properties. Final thing to do is create the event that fires when this activity executes. In the Method Invoking field enter createTask and click enter. Again is creates our event handler and interface for us. Again we’ll come back to this is a little while.

Now that our task has been created for the assigned user, we need to add some waiting functionality to enable the workflow to wait for the task to be completed by the user. We do this using the While workflow component.
Drag and drop a While component from the Windows Workflow section in the toolbox between the createTask1 and the end of the workflow. In the properties window expand the Condition property. In the first Condition property select Code Condition from the drop down, and in the second condition type notFinished and press enter. This will create an event handler for you in code where you check whether the While condition has been met (ie has the user completed their task).

Now we want to add an activity to the centre of our While loop. Here we’ll place an onTaskChanged. This basically means that the While loop will execute and check our code condition, every time our task is edited. It won’t be able to exit out of the While loop until our method notFinished returns false (which means it is finished!). Drag an onTaskChanged component and drop it in the middle of our While loop. You’ll see in the properties window there are quite a few things we need to set:
AfterProperties = click the ellipses and bind to a new member called afterProps
BeforeProperties = click the ellipses and bind to a new member called beforeProps
CorrelationToken = select taskToken from the drop down
Invoked = onTaskChanged. When you’ve typed it in press enter to create the event handler for you.
TaskId = click the ellipses and bind to the existing member called taskId (see image below).

The properties window for onTaskChanged should now look as below:

You should notice that the CorrelationToken is set to the same value as in createTask1. This ensures that the same task that was created will be updated. Also with afterProps and beforeProps, as before when you bound and created a new member, afterProps and beforeProps are variables that are created in code.
The final component we want to add to our workflow is the CompleteTask activity. Drag and drop a CompleteTask component between the While component and the stop workflow activity. In the properties set the Correlation Token to taskToken from the drop down, again this makes sure we are working with the same task created earlier in our workflow. With the taskId click the ellipses and bind it to the existing member of taskId. You can see below how the properties for completeTask1 should look.

Now we’ve added all the components to our workflow. Our workflow designer should look as below:

Now we’ve got all our components added, and event handlers and methods created, we need to add some code to Workflow1.cs.
Right click on Workflow1.cs and click View Code. The first bit of code we need to add declares a few variables we are going to need in our workflow. Just above the onWorkflowActivated method add:
private String assignee = default(String);
private String instructions = default(String);
private String comments = default(String);
These three values are ones that we are going to get from our DemoInitiation form. These properties are passed to the workflow as an XML string represented by the InitiationData property of the SPWorkflowActivationProperties object. To access these properties we need to parse this XML string. This is where we make use of the generated class based on the schema of our initiation form that we did in step 4 and added to our project as InitForm.cs. To get these values add the following code to the onWorkflowActivated method:
workflowId = workflowProperties.WorkflowId;
XmlSerializer serializer = new XmlSerializer(typeof(InitForm));
XmlTextReader reader = new XmlTextReader(new System.IO.StringReader(workflowProperties.InitiationData));
InitForm initform = (InitForm) serializer.Deserialize(reader);
assignee = initform.assignee;
instructions = initform.instructions;
comments = initform.comments;
To make use of XmlSerializer you’ll need to add a using System.Xml.Serialization at the top of the class (if there isn’t one already).
The next method we need to add some code to is createMethod. Here we want to set some properties of a task as this method fires just before the task does actually get created. Here’s the code:
taskId = Guid.NewGuid();
taskProps.Title = "Demo Task";
taskProps.AssignedTo = assignee;
taskProps.Description = instructions;
taskProps.ExtendedProperties["comments"] = comments;
taskProps.ExtendedProperties["instructions"] = instructions;
as you can see there are a predefined properties such as Title and AssignedTo to use, and if there’s any other properties you want to name and create yourself you can use the ExtendedProperties. This is a hash table so you can name things as you like.
The final bit of code we need to add is probably the most complex to get our heads around. We need to add a private Boolean variable called isFinished. Place this just above the notFinished method:
private bool isFinished;
Now our While loop calls the notFinished method. One of the objects passed in is ConditionalEventArgs which has a property called result. If result is set to false, the while loop will end, if result is set to true, the while loop continues. As you should be able to work out, the variable above we created isFinished will be true once the task has been finished. Therefore we have to negate it to set it’s value to the ConditionalEventArgs result property. In the notFinished method type the following code:
e.Result = !isFinished;
The last thing we need to do is actually set isFinished when our task gets edited ie when onTaskChanged event files. In here we just need to parse out the isFinished value from our afterProps object. At the code below to the onTaskChanged method:
isFinished = bool.Parse(afterProps.ExtendedProperties["isFinished"].ToString());
And that’s it. Build your solutions, and hopefully everything compiles succesfully. Now I was also going to include instructions on how to deploy this workflow, but I’m going to save that for tomorrow. This is definitely the longest blog post I’ve ever written and I think my fingers need a break. Don’t worry though I’ll post a link to it here in the comments as soon as it’s done.
I hope this post is some use to some of you who’ve been struggling with the SDK example. We’ve created our workflow in a slightly different order to the SDK, and perhaps me explaining one or two things in a slightly different way will help you get going with this HelloWorld type workflow.
Feel free to post any questions or comments. I’ll do my best to answer them. See you again tomorrow for the steps on how to deploy this workflow!