MOSS Workflow Examples – Custom Initiation/Instantiation Form (using InfoPath)

Previously, I posted a guide to creating and deploying a very simple custom Association form for a MOSS workflow. This time, I will walk through the steps to create a custom Initiation form, and also a bit of detail on consuming the data from the Initiation form from your workflow code. To reiterate what I said in the Association form walkthrough, what I am creating here is not a form you would use in a real workflow – the intent is to demonstrate the process with as much noise and detail stripped away as possible.
As I describe in my other post, the Association form is displayed when you connect your Workflow Template to a document/form library, list, or content type (the action known as creating an association). The Initiation form is displayed when the user actual starts or instantiates the workflow on an item in a list or document library. The intent is to collect startup information for the workflow. The information collected by the Instantiation form may be the same as on the Association form (allowing the user to override the defaults) or it may be completely different information. Have a look at  http://msdn.microsoft.com/en-us/library/ms481192.aspx if you would like to see Microsoft’s definitions.
Before we start, have a look at my previous post describing my base environment for creating these examples.
1) Create a new site
I used a new web application, and a new site collection created using the Team Site template. I named my site InitiationFormDemo;
2) Create Form Library
On this new site, create a Form Library (which I named Workflow Form Library);
3) Create Task List
Also create a new Task List. I called mine Workflow Tasks. At this point, your site home page should look something like the picture below.
Initiation Form Demo Site
4) Create Workflow Project
Launch Visual Studio 2008. Create a new project. Expand the C# project tree, select Workflow, and select the SharePoint 2007 Sequential Workflow. Name the project “MyWorkflow”. The create project dialog should look like the picture below.
Create Workflow Project
5) Set the properties for the project as shown below
Workflow Project Settings 1
Workflow Project Settings 2
Workflow Project Settings 3
6) Finish Creating Workflow Project
Click finish. Normally, we would change the workflow name in the project, add some activities, some code, etc., but this is not necessary for this example. The project should look something like this.
Workflow Project
7) Create Custom Initiation Form in InfoPath
Now we will create the InfoPath Initiation Form. Launch InfoPath and select Design a Form Template. Select the settings as shown below (Form Template, Blank, Enable browser-compatible features only).
InfoPath 1
8 ) Design the Custom Initiation Form – Create Data Source for Submission
In the InfoPath Designer, select Tools | Data Connections… and click the Add button. Create the new data connection as shown in the following pictures.
InfoPath 2
InfoPath 3
InfoPath 4
Click Finish and Close to get back to the main InfoPath window.
9) Create a Custom Field for the Form
In the Task Pane, under Design Tasks, click on Data Source. Right click on myFields, and select Add to add a new field to the schema. Create a new field as shown below, and click Ok.
InfoPath 5
10) Add the Custom Field to the Form
Drag and drop the My Setting field onto the design surface, to create label and text box for it. Also add a Button control, and change its label to “Submit”. Your form should look something like the picture below.
InfoPath 6
11) Add Logic to the Submit Button
Double click on your Submit button to display the Button Properties dialog. Click on the Rules… button, and click Add and then Add Action. Select options as shown below, and click Ok.
InfoPath 7
Click Add Action again, and set the options as shown below, and click Ok.
InfoPath 8
You should now have two actions, as shown below.
InfoPath 9
12) Set Form Security Level
Finally, we must set the form trust to Domain. Select Tools | Form Options…, and select Security and Trust. Unselect the checkbox Automatically determine security level (recommended), and click the Domain radio button, as shown below, and click Ok.
InfoPath 10
13) Save the Form Template
Save the form to disk (File | Save). You can save it anywhere you want, as long as it is not your Visual Studio project folder. I just save mine to a Forms folder in My Documents. Name the form MyInitiationForm.xsn for this example (in practice you can name it whatever makes sense).
14) Publish the Form Template
Now we want to publish the form. This did not entirely make sense to me, but when you select File | Publish…, on the first page of the publish dialog we will select To a Network Location even though we will actually publish it to our Visual Studio workflow project folder.
Publish 1
Click Next, and then browse to the location where you will publish the form. In this case, we want to publish to your workflow project folder, as shown.
Publish 2
Type a name for your form (I used MyInitiationForm.xsn), click Ok, and Next. On the next form, clear the text box and click Next (this is important, the form will not work if you do not clear that text box!)
Publish 3
When you click Next, a warning will pop up, as shown below. Click Ok to continue.
Publish 4
Click Publish and Close, and then exit InfoPath.
15) Retrieve Form ID to Use in Workflow Project
In Windows Explorer, navigate to your workflow project folder, right click on the InfoPath form you just published there, and select Design. When the form opens in design mode, select File | Properties… to display the properties dialog shown below.
Get Form ID
Select the ID as shown, and copy it to the clipboard. Click Ok and exit InfoPath.
16) Modify Workflow Project to Reference Custom Initiation Form
Go back to Visual Studio 2008, and open you workflow project if it is not still open. Open the workflow.xml file. The default file looks like this:
<?xml version="1.0" encoding="utf-8" ?>

<!-- Customize the text in square brackets.
     Remove brackets when filling in, e.g.
     Name="[NAME]" ==> Name="MyWorkflow"
 -->

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <Workflow Name="MyWorkflow"
             Description="My SharePoint Workflow"
             Id="0d94af3a-45e7-4035-b351-9a10fc41018d"
             CodeBesideClass="MyWorkflow.Workflow1"
             CodeBesideAssembly="MyWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=96c40524715e44e9">

      <Categories/>
      <MetaData>
         <!-- Tags to specify InfoPath forms for the workflow; delete tags for forms that you do not have -->
         <!--<Association_FormURN>[URN FOR ASSOCIATION FORM]</Association_FormURN>
         <Instantiation_FormURN>[URN FOR INSTANTIATION FORM]</Instantiation_FormURN>
         <Task0_FormURN>[URN FOR TASK (type 0) FORM]</Task0_FormURN>
         <Task1_FormURN>[URN FOR TASK (type 1) FORM]</Task1_FormURN>-->
         <!-- Modification forms: create a unique guid for each modification form -->
         <!--
         <Modification_[UNIQUE GUID]_FormURN>[URN FOR MODIFICATION FORM]</Modification_[UNIQUE GUID]_FormURN>
         <Modification_[UNIQUE GUID]_Name>[NAME OF MODIFICATION TO BE DISPLAYED AS A LINK ON WORKFLOW STATUS PAGE</Modification_[UNIQUE GUID]_Name>
         -->
         <StatusPageUrl>_layouts/WrkStat.aspx</StatusPageUrl>
      </MetaData>
   </Workflow>
</Elements>
Paste the ID from your InfoPath form properties into the <Instantiation_FormURN> element, and uncomment the element (be careful that the other commented out elements stay that way – or delete the ones you are not using as I did):
<Instantiation_FormURN>urn:schemas-microsoft-com:office:infopath:MyInitiationForm:-myXSD-2009-04-06T02-58-49</Instantiation_FormURN>
Of course, your actual URN will be different than mine.
Add the following new attribute to the <Workflow> element:
InstantiationUrl="_layouts/IniWrkflIP.aspx">
Your workflow.xml file should now look something like this:
<?xml version="1.0" encoding="utf-8" ?>
<!-- Customize the text in square brackets.
     Remove brackets when filling in, e.g.
     Name="[NAME]" ==> Name="MyWorkflow"
-->
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <Workflow Name="MyWorkflow"
             Description="My SharePoint Workflow"
             Id="0d94af3a-45e7-4035-b351-9a10fc41018d"
             CodeBesideClass="MyWorkflow.Workflow1"
             CodeBesideAssembly="MyWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=96c40524715e44e9"
             InstantiationUrl="_layouts/IniWrkflIP.aspx">
      <Categories/>
      <MetaData>
         <!-- Tags to specify InfoPath forms for the workflow; delete tags for forms that you do not have -->
         <Instantiation_FormURN>urn:schemas-microsoft-com:office:infopath:MyInitiationForm:-myXSD-2009-04-06T02-58-49</Instantiation_FormURN>
         <StatusPageUrl>_layouts/WrkStat.aspx</StatusPageUrl>
      </MetaData>
   </Workflow>
</Elements>
Save the file and close it.
17) Make Sure the Custom Initiation Form will get Copied With the Workflow Feature
Next, open the feature.xml file. It will look something like
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="15fdd97f-db32-44c1-96cc-cab49acecd36"
         Title="MyWorkflow 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" />
   </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>
Find the <ElementManifests> tag, and under that, add a new <ElementFile> element inside it as shown:
<ElementManifests>
   <ElementManifest Location="workflow.xml" />
   <ElementFile Location="MyInitiationForm.xsn"/>
</ElementManifests>
Save the file and close it.
18 ) Rebuild your workflow solution, and deploy it.
19) Test it Out
Back in IE, navigate to your form library. Since I’ve not created a custom association form in this example, you can create the association using the default form (if you have set up your project to auto-associate, you will not need to do this manually).
Since we want to initiate a workflow, first we need to add a document to the library. I just clicked upload and selected a random file from my desktop. Hover over the file you uploaded and left-click to bring up the context menu. Select Workflow from the menu. Then click on MyWorkflow to start the workflow. This should bring up your custom instantiation form as shown below.
Start Workflow
Enter some text, and click Submit. You will see an animation showing that MOSS is working, and then you will be brought back to the Form Library page. The status of your workflow should show as complete, since the workflow does not actually do anything.
20) Accessing the Initiation Form data in your workflow
I will now quickly show how to access your initiation data from your workflow. We will simple pull out the string entered and log it.
Open your workflow project in Visual Studio, and open your workflow in design view. Add a new logToHistoryListActivity as shown below, and set the HistoryDescription property as shown (set it to a String Field named HistoryDescription in your workflow).
Add LogToHistoryList LogToHistoryList Properties
Right click your logToHistoryListActivity and select Generate Handlers. In the event handler, add code as show below:
public String HistoryDescription;
private void logToHistoryListActivity1_MethodInvoking(object sender, EventArgs e)
{
      String MySettingValue = workflowProperties.InitiationData;
      HistoryDescription = "Initiation String Entered: " + MySettingValue;
}
Rebuild and deploy your workflow, and execute it as in Step 19. Click on the Completed link as shown below.
In the Workflow Status you will now see a history event as shown below, and the initiation string is shown as an XML string, with a <MySetting> element and the string I entered. To use this data in a workflow, you would parse the XML and go from there (or generate a class from the schema and load the XML into that).
Workflow Status
Well, there it is. A custom Initiation form using InfoPath.
Next time – custom Task forms!

George Carlin

Today the world lost one of its most interesting personalities, and one of my personal heroes. George, I will miss you…

Re-focusing

So, the time has come to re-focus my blog a little around what I am currently working on. In the last year, I have gone through a fairly significant transition in my career. After close to a decade in a product-oriented startup, I have moved into a consulting role at T4G. This is a big change for me, at least it feels like it – the mental shift from focusing on products, product features, and product life-cycles  to focusing on client engagements and project-oriented work. My mind tells me that in many ways the two are not so different – they just feel very different.

The main focus of my work (at least initially) is on portal technologies, specifically SharePoint. In addition to the engineering and mechanics of implementing SharePoint solutions, I am focused on a number of other related topics:

  • A repeatable approach to delivery of SharePoint solutions
  • Process/methodology models for SharePoint implementation
  • Estimating models for SharePoint projects
  • The art of the possible – what could clients be doing with SharePoint

I will also be spending a significant amount of time establishing a Moncton office for T4G. By the way, if anyone knows any SharePoint resources (or good .NET or ASP.NET resources in the area, send them my way 🙂 ).

While my new role is as a consultant in an consulting company, I do not plan to abandon my roots in software development, software development processes, and programming. I also maintain a strong interest in innovation processes. Finally, there are a number of technology areas I am continuing to investigate, including Tablet PC applications, Silverlight, Office Business Applications, Social Networking, etc.

I am also hoping to have more time to blog a little more regularly 🙂

My new toy

Well, over the last month I have acquired a new toy – a telescope. This is the first scope I have owned in many years (since the 70s actually), and the first one I have used since my university days of the early 1980’s. Needless to say, things have change significantly in that time. I actually spent a considerable length of time debating what I actually wanted to buy – a large Dobsonian vs a small portable refractor which would be great for imaging vs. a fancy computerized Schmidt Cassegrain (or similar).

Instead of going through all my internal debates, I will just jump to the end result. I ended up buying a Celestron CPC 1100, which is an 11 inch, fork-mounted, computerized Schmidt Cassegrain, and is pictured below. I purchased the scope from Astromechanics in Barrie, ON. Despite some adventures with the shipping company, who “misplaced” the tripod for a few days, I must say dealing with Dave with Astromechanics has been a pleasure.

 telescope3 The telescope itself is, to say the least, really cool. As an astronomer/physicist-turned-software guy, there are many things on this scope to draw my attention. Mechanically, the scope, mount, and tripod are all very good. I have not seen any marks or blemishes, everything fits together cleanly, and is extremely steady.

The optics seem extremely good as well. Last night was my first real night of observing. The sky was very transparent, but there was a fair amount of instability in the atmosphere (really only noticeable when looking at the moon and Saturn, though). I was very impressed with the views. My first target was M42 (the Great Nebula in Orion). While I have seen this many, many times before, it remains one of my favourites, and was no disappointment in my new scope. Using a Baader Planetarium Hyperion 21 mm eyepiece (giving a magnification of 133x and a field of view of about half a degree), the view was breathtaking. A great deal of detail was visible, with tendrils and wisps extending pretty much across the field.

Observing Saturn next, I was impressed with the detail which could be seen in the rings during occasional moments of steadiness, along with hints of detail on Saturn’s cloud tops.

I also spent quite a bit of time looking at various open clusters (M36, M37, M38, M41). I could sit and stare all night at this sparkling collections (except of course I was freezing various body parts off!).

What impresses me most right now, though, is the alignment and GoTo software in this scope. For those not familiar with these products, this is a truly amazing piece of programming. All you have to do it level the tripod, set up the scope, wait for it to lock on the GPS signals, then point it at any three bright objects (stars, planets, or the moon), and the telescope figures out all the details it needs to be able to automatically go to any of ~40K objects in its database. The first couple of nights I was out, my tripod was still missing, so I had the scope set up on a folding portable workbench. I could not level it very well, and used three stars in the same part of the sky for alignment. Even with this, the go to consistently centred all of the objects I selected. Having now set the scope up on its tripod, and used stars more “distributed” around the sky to align, go to seems to be perfect. I have yet to see any problems, hiccups or glitches (and those of you who know me, know I can break almost any computer!).

Given the amount of stuff out there which you have to fight with to make work, it is refreshing to use something that just works!

Over the next few months, I hope to get into doing some imaging. I will post the results if I am in any way successful.

A Picture of the Multicore Crisis -> Moore’s Law and Software

I was reading A Picture of the Multicore Crisis, and got to thinking of something which has bothered me for a long time. This issue is related to Moore’s Law and the growth of processing capacity (whether through raw clock speed, or the multicore approach, or magic and hampsters). Looking at the last 10 years or so, we probably have something like 10-20 times the processing power we had 10 years ago.

As a producer of server-side software, a user of server software, etc., it makes me wonder – why are my servers (document management, document production, and many others) not providing a corresponding increase in throughput? Why do many server systems maintain the same performance over time, or offer only marginal improvements?

(I leave aside client side performance for now, because on the client side much of the performance improvements have shown up in different ways, such as new capabilities like multimedia, prettier graphics in the UI, the ability to multitask and keep 10 different applications open at the same time).

So, why are my servers not 10 times as fast as they were? I can think of a few reasons:

  1. As has been discussed in other places, the shift from clock-speed-driven improvements to a multicore approach has had an impact. Much software, especially older software, is not written in a way which takes advantage of multiple processors. And often, re-engineering this software to better use multiple processors is non-trivial, especially when you have to worry about things like backwards compatibility and supporting a large number of customers, finding time to add the new features product management wants, etc. Very few of us can afford to divert a significant group of our development resources for an extended period of time, and it is frequently hard to justify from a business perspective.
  2. Even if your software is architected for multiple processors, oftent he algorithm is inherently “single threaded” in places, which throttles the whole process.
  3. Also, even if you are well architected for multiple processors, this does not come for free. The overhead introduced in managing this algorithm can easily consume a non-trivial portion of your processor gains.
  4. Even excluding the shift to multicore, much software has not kept up with performance improvement provided through pure clock speed. There are a number of reasons for this:
    • We are frequently very feature driven. The desire to compete, expand and grow often leads us to add features to existing software at an alarming rate. Wile this is necessary from a business perspective, often the addition of these new features slows down the software faster than the hardware speeds it up. Note, this is why I think it is very important to be architect software so as to be able to isolate “core” processing from “features”. This way, features can be removed from the configuration when not needed, and not allowed to impede performance. Also, this is why it is important in each cycle of development on a product to assess whether performance on the same hardware is at least as good.
    • Processing power is not the whole story (yeah, I know, we all know this). Much of our software is not entirely CPU bound. The bottlenecks are often elsewhere. Much of our processing, especially for large documents, is more bound by memory, disk speed, network speed, and dependencies on other systems. Given that, there is only a limited amount of benefit to be gained through pure processor speed.

MacBook Pro versus Non-Mac Laptop

I am speculating about my next laptop purchase, and as always, I like to think of alternatives to my current environment (which is an Inspiron 9400, 2.0 GHz core Duo, 2 gb of RAM, running Vista). I do not own a desktop machine, and really do not see myself going that route, unless I were to get a new iMac purely as a luxury.

I am thinking of the following options:

  1. An Apple MacBook Pro (17″, 2.4 GHz, 2 gb of RAM, High resolution display, everything else pretty much standard)
  2. Dell Inspiron 1720, configured pretty much the same as the MacBook (except with only a 2.2 GHz processor) with Windows Vista or XP
  3. The same Dell, but loaded with some flavour of Linux.

(note that whatever choice I make, I would still have to run Vista and/or XP somewhere on the machine in order to co-exist with the real world)

These options appear very similar to me. I even configured the Dell with stuff I might not care about (like a built-in webcam), in order to make the comparison “fair”.

The main difference I see is the price. I can get the Dell for about $1800 (Canadian), whereas the MacBook Pro comes in at over $3200. Is there anything about the Apple which justifies this price, beyond being “cool”? Is the price of the Mac OS really $1400? Or is there something else intangible here?

As much as I might like the MacBook alternative, I cannot really see justifying the cost.

Can anyone tell me why I (or they) would let Apple overcharge them like this?