Table of Contents for on SharePoint 2007 WF Authoring using Visual Studio.
1. Setting up your environment for writing VS2005 workflows.
2. Writing an ultra basic workflow, deploying it, and slicing dicing how it worked.
3. Making that workflow more complex, adding if/else, and a bunch of activities that sort of make it more interesting.
4. Adding user interaction to that workflow using Infopath forms.
5. Authoring SharePoint 2007 Workflows using VS2008.
Okay, so now that your environment is all set, we can begin writing an ultra basic WF.
The steps are more or less the same for a Sequential WF and a State Machine WF, but since all of us know what flowcharts are, and sequential WFs are very similar to flowcharts, I am going to use sequential WFs to demonstrate my point. What we are going to do, is write a simple workflow, and tie it to a simple custom list with 1 column - Title. This simple workflow when instantiated, changes the title of the list item to a number between 1 to 6 randomly (much like a dice). THATS IT (Keep it simple huh?). No other forms, no craziness. With such a basic WF, I will be able to demonstrate how this thing got built, how it got deployed, and how you can debug that sucker.
As an outline, you need to perform the following steps to author such a workflow -
- Create a project in VS2005 (For VS2008, please see instructions here)
- Think about your logic, and draw that on the WF designer.
- Fill in the code for your WF.
- Create a feature.xml
- Create a workflow.xml
- Deploy
- Try and run it.
- Debug
Let us take these 1 by 1.
1. Create a project in VS2005. (VS2008 instructions here)
Using VS2005, create a new project called RollOfDiceWF in VS2005. Base this project in the SharePoint Sequential WF template.
2. Think about your logic, and draw that on the WF Designer.
Okay, now in this workflow, I have no user input, and really no branching logic. All I need to do really is, calculate a random number between 1-6, and then simply update the list item's title column with that random number. Hmm .. sounds like a single activity that can get a hold of that item, and do the necessary updating should do the trick. Okay - I guess all I need to do is drop a single "Code Activity" on the WF Designer.
Now, the project that you just created, it's designer surface looks a bit like this to begin with -

This is quite interesting. What is "onWorkflowActivated1" doing there? Well - any sharepoint workflow, needs to have that as it's first activity. That activity will give you a whole bunch of goodness, such as access to the list item you will need shortly. On the toolbox, you will see a number of activities that you can choose from. Not all can be used in SharePoint workflows. Notably, any .NET 3.0 activity to do with Transactions or Compensation won't work in SharePoint 2007. Luckily, an activity you can indeed use, is the CodeActivity. Go ahead and drag drop the code activity on the surface of your workflow, right below "onWorkflowActivated1" as shown below.
Now, what is that red exclamation mark right next to the code activity? Well - it is telling you, that something is wrong. When you hover over it, it tells you that the Property ExecuteCode isn't set. This is where you need to write some code.
3. Fill in the code for your WF.
Okay, now how exactly you fill in the code, depends on the activities you dropped. Different activities have different needs. As I complicate this WF in further blogposts, I will have the opportunity to elucidate a few common scenarios. But, for now, just double click on the CodeActivity, and that should take you to a place, where you can write the code. Also, it will get rid of that exclamation mark. This works very much like ASP.NET (conceptually atleast). There is a .xoml file that is graphic in nature, and there is a .cs file, that is code-behind(ish). (Read WF Basics). So anytime you can right click on the surface of that WF, and choose "View Code" and it brings you back to the innards of your WF.
Now go ahead and modify the code to look like as below:
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
Random rnd = new Random() ;
workflowProperties.Item["Title"] = rnd.Next(1, 6);
workflowProperties.Item.Update();
}
As you can see, I am getting a random number between 1 and 6, and I am using workflowProperties.Item to access the List Item that this workflow is operating upon.
Thats it, the workflow is written. Now lets start talking about, what it will take to deploy this workflow.
4. Create a feature.xml
This visual studio template insists that you install your WF as a feature. Is that a bad thing? Heck no! WF's can contain many peices, especially if you are using forms, and custom activities. It's hella nice if the whole thing can be deployed/retracted as a solution/feature. So the next step is to go ahead and create a feature.xml. Well, under the DeploymentFiles\FeatureFiles folder - there already IS a feature.xml. You just need to add stuff to it.
Adding stuff to it is made a lot easier by using code snippets. The snippets intellisense probably won't work. What you need to do is, in VS2005, go to Tools --> Code Snippets Manager, and in the dialog box, choose XML, in the drop down, and click on "Add", and choose C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\Template\Xml.
Once intellisense is added in, go ahead and add the following snippet -
Insert Snippet > SharePoint Server Workflow > Feature.Xml Code
Once the feature is inserted, go ahead and modify the green place holders, so your feature.xml looks a bit like this -
<Feature Id="7C5366F5-46EE-48bc-BF1E-ABBBE24DA04C"
Title="Roll of Dice WF"
Description="This feature is a workflow that rolls dice for you"
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" />
</ElementManifests>
<Properties>
<Property Key="GloballyAvailable" Value="true" />
<!-- Value for RegisterForms key indicates the path to the forms relative to feature file location -->
<!-- if you don't have forms, use *.xsn -->
<Property Key="RegisterForms" Value="*.xsn" />
</Properties>
</Feature>
Note that I put in a GUID at Id="". That is created using GUIDGEN, which can be accessed using Tools --> Create GUID in VS 2005 (this tool has been around since VC6 times).
5. Create a Workflow.xml
Similarly, edit the OOTB workflow.xml to as follows:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Workflow
Name="Roll Of Dice WF"
Description="This workflow rolls dice for you"
Id="92654684-543C-4045-981A-4E02FC9234E2"
CodeBesideClass="RollofDiceWF.Workflow1"
CodeBesideAssembly="RollofDiceWF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=publicKeyToken"
StatusUrl="_layouts/WrkStat.aspx">
<Categories/>
<!-- Tags to specify InfoPath forms for the workflow; delete tags for forms that you do not have -->
<MetaData>
<AssociateOnActivation>false</AssociateOnActivation>
</MetaData>
</Workflow>
</Elements>
Now, you would note that
a) I haven't put in the publicKeyToken yet. That is coming shortly.
b) I took out a bunch of stuff from this workflow.xml file. Well - we don't have any custom input forms, so you have to take that junk out. Otherwise, the WF won't work.
6. Deploy
Okay good. We're almost there.
In order to deploy, you need to do two things
a) Strongname the assembly.
Right click on the project, choose properties, and under signing, go ahead and create a new key. (This effectively strong names the assembly). Now go ahead and build the project. This will create the assembly, but won't actually deploy it yet. At this time, use a tool like Reflector to get the PublicKeyToken for the assembly, and update your Workflow.xml file with that public key token.
b) Actually deploy this WF ;-)
Now this is easy. Right click properties on the project, go to Build Events, and in the Post-Build event command line, change the last word from "NODEPLOY" to "DEPLOY".
(Seriously, that's it!)
Now, rebuild all the project. As a part of "Rebuild" the project will also deploy the solution & feature. The way it does all this, is by leveraging the PostBuildActions.bat that is a part of the project already. You can view the output of PostBuildActions.bat using Debug --> Output.
Should you choose to deploy this in production, simply change the project's configuration from Debug --> Release, and now it will create a .wsp for you. Pretty Nifty.
Great, now we can start playing with this.
7. Try and Run it
- Go to the sharepoint site that this WF got deployed on (localhost:80), and create a new custom list. By default it has a single colum in it called "Title".
- Go to list settings, workflow settings, and add an association of the Roll of Dice WF as shown below -
- Go back to the list, and add a new List Item.
- Click on the List Item, and choose Workflows.
- Click on the RDWF link. (RDWF, because that was long descriptive (!) meaningful name I gave in the screenshot above).
- You would note that the WF runs, as indicated by the SharePoint spinner, and the results are then shown as below -
Wow, I got a 5 in the first try. :-). Not bad!
Go ahead and peek around a bit. Look under Site Collection Features, you would see a feature for this workflow has been added and activated for you.
Also look under central administration > Operations > Solution Mgmt. You would see that the WF/Feature has been packaged up as a solution and deployed for you.
8. Debug
Life would be so much better if I never had to debug anything. But we all get stuck with debugging every now and then.
Debugging WFs is hella easy.
a) Go to project properties, under Debug, choose "Start Browser with URL", type in http://localhost.
b) Now set a breakpoint on the WF designer (yeah seriously, try it), and hit F5. VOILLA .. WF DEBUGGING. w00t!
The downer however is that managed code and WF cannot be debugged together (which really sucks). So, in order to debug inside an activity, you have to attach to w3wp.exe and uncheck workflow debugging.
Okay wow, this ultra simple WF has been a fairly long blogpost. Next I will complicate the WF a tad bit, but to save myself a whole amount of typing, I will simply reuse this above WF on build on top of it.
Read the next post - Complicating the above WF.