OnTaskCreated activity is trouble.

I meant to write this for quite a while and kept forgetting about it...
 
We've had numerous situations while developing Windows Workflow Foundation workflows in which either the OnTaskCreated or the OnTaskChanged activity would not be called ("fire"). The behaviour was non-deterministic, whereas sometimes it would work and then it wouldn't. E.g. I'd add an arbitrary line of code and then it would work.
 
Well, long story short, after following all the paths that could normally go wrong, like checking whether the taskID and the taskProperties are properly set, and also to check that all objects could serialize ok, and installing all relevant Hotfixes and Updates etc., I resorted to a recommendation to simply leave out the OnTaskCreated activity and have not had any problems ever since.

Published: Aug-27-09 | 2 Comments | Link to this post

Task Links for Custom SharePoint Workflow Notifications

If you're building a workflow solution using Windows Workflow Foundation and Windows SharePoint Services 3.0, you have to implement aspx forms. What's more, you also have to design your own task (or other) notification forms.
 
I guess everyone would want to have the convenience of having links back to the task, the task item and the workflow status. Even the ability to "Connect Outlook" to the Workflow Tasklist would be nice, so that all tasks are not only available on the web, but also within Outlook.
 
Of course these links need to be constructed at runtime, as IDs and names depend on the specific lists and task items being used.
 
The Html Template
The resource that is used to dynamically build these links is rather simple:
 

 <DIV>

    <P style="MARGIN-BOTTOM: 8px; BACKGROUND: blue">

        <B><SPAN style="COLOR: white">&nbsp; Workflow Links:</SPAN></B>

    </P>

    <DIV style="MARGIN-LEFT: 8px">

        1. <A href="{ListItemUrl}"> Link to the List Item the workflow was started on</A> <BR>

        2. <A href="{TaskUrl}"> Link to the Task</A> <BR>

        3. <A href="{WorkflowStatusUrl}"> Link to the Workflow Status</A> <BR>

        4. <A href="{ConnectOutlookUrl}"> Connect Outlook to Workflow Task List</A> <BR>

    </DIV>

 </DIV>

 

The essential parts are marked in red. These are the placeholders we have to change at runtime.

 

ListItemUrl & TaskUrl

The code to exchange the ListItemUrl and the TaskUrl is quite simple too. As you can see the "workflowProperties" and the "activity" have all the data we need to concatenate the pieces for the links:

 

String webUrl = workflowProperties.WebUrl;

bodyStr = bodyStr.Replace("{ListItemUrl}", webUrl

                           + workflowProperties.ListUrl + "/DispForm.aspx?ID="

                           + workflowProperties.ItemId.ToString());

bodyStr = bodyStr.Replace("{TaskUrl}", webUrl + workflowProperties.TaskListUrl

                           + "/DispForm.aspx?ID=" + activity.ListItemId.ToString());

 

WorkflowStatusUrl

For the WorkflowStatusUrl we need to get the GUIDs for the List that holds the item the workflow was started on, as well as the Workflow Instance and then add the curly braces and escape the "-". The following code section has the little helper method that does that, as well as the code to concatenate the link:

 

private String formatGuidString(String s)

{

    s = "%7b" + s;

    s = s + "%7d";

    s = s.Replace("-", "%2d");

    return s;

}

 

...

 

String strListID = formatGuidString(workflowProperties.Workflow.ParentList.ID.ToString());

String strInstanceID = formatGuidString(workflowProperties.Workflow.InstanceId.ToString());

bodyStr = bodyStr.Replace("{WorkflowStatusUrl}", webUrl + "/_layouts/WrkStat.aspx?List="

                          + strListID + "&WorkflowInstanceID=" + strInstanceID); 

 

ConnectOutlookUrl

Last not least, the link that I like the most. The Connect to Outlook menu command in SharePoint is already a great value, but with Workflows I find it quite cumbersome to send users to the Workflow Tasklist to have them manually connect to Outlook from there, especially when this list is usually hidden from the users.

 

The connection to Outlook is achieved by calling a custom protocol (stssync). The following string (called "strConnectTo" in the following code) is a generalized version, for which we again will have to substitute the placeholders:

 

stssync://sts/?ver=1.1&type=tasks&cmd=add-folder&base-url={serverUrl}&list-url={taskListUrlPlusSlash}&guid=%7b{taskListGuid}%7d&site-name={siteName}&list-name={listName}

 

The 5 placeholders are actually also easily replaced:

 

strConnectTo = strConnectTo.Replace("{serverUrl}", workflowProperties.WebUrl);

strConnectTo = strConnectTo.Replace("{taskListUrlPlusSlash}", workflowProperties.TaskListUrl + "/");

strConnectTo = strConnectTo.Replace("{taskListGuid}", workflowProperties.TaskListId.ToString());

strConnectTo = strConnectTo.Replace("{siteName}", workflowProperties.Web.Title);

strConnectTo = strConnectTo.Replace("{listName}", workflowProperties.TaskList.Title);

bodyStr = bodyStr.Replace("{ConnectOutlookUrl}", strConnectTo); 

 

And that's it!


Published: Aug-24-09 | 0 Comments | Link to this post

"Real" Workflow becomes a differentiating factor

Years ago, when talking to customers, I realized the importance of workflow engines that are integrated with content management solutions. However, "workflow" solutions had been around for a long time and never really made it into the mainstream. They had an aura of complexity to them and came in so many different shapes and forms, that it was next to impossible to find a standard way of integrating them with Line of Business systems.
 
The introduction of the Windows Workflow Foundation (WF) in 2006 also caused some disruption, as it came with its share of bugs and issues. But it also showed how much demand is out there for a workflow engine, as the blogs and forums filled up pretty quickly, which indicates how much momentum the WF has gained by now.
 
However, the best evidence for how much value customers see in real workflow solutions was a recent article which stated that SaaS Provider (modern word for: hosting company ;-) Emantra is absorbing the licensing cost for Nintex, which is a solution built on top of WF, making it much more easy (especially for non-programmers) to ad-hoc build workflow solutions.
 
Whether customers will go with solutions like Nintex, or the plain WF is being used, or another workflow engine, I am sure people are now finally grasping the fundamental advantages that a "real" workflow solution provides over "so-called" workflow solutions that scripted, based on simple trigger mechanisms, or cobbled together otherwise.

Published: Jun-30-09 | 0 Comments | Link to this post

ASPX Workflow Forms cntd.

Alright, just as I wrote a blog post about the lack of documentation around aspx workflow forms, here comes some news from Microsoft on it:
 
"In Visual Studio 2010, you’ll be able to create list and site level workflows as well as create aspx association and initiation forms." Source: Somasegar's Weblog.
 
To my knowledge, the next pre-release version of Visual Studio 10 will have also a rewritten engine of the Workflow Foundation (faster, extended functionality), which was mentioned at the last PDC.
 
Can't wait to see if the improvements are going to be as good as promised. I'll definitely check and report back here on my blog about the findings.

Published: May-04-09 | 0 Comments | Link to this post

ASPX Forms for SharePoint Workflows

We just needed to implement ASPX forms for a SharePoint workflow. Knowing that this was not very well-documented when SharePoint 2007 came out, I was prepared for some extensive searching to find what I was looking for ...except, after 2 1/2 years since that last SharePoint release, there's still no proper documentation available on this yet. At least I couldn't find it. It also doesn't help to repeatedly hear from MS executives, like Chris Capossela, that "about 20,000" pages of documentation have been added in 2008" ...go figure.
 
Alright, back to the usual rescue: the SharePoint community!
 
There is actually one example for ASPX forms that shipped with the WSS 3 SDK. It's called ASPXCollectFeedback. I assume it's there just for me to make my point: Serge Luca details nicely all the problems that have to be fixed in this project before it can be run. And then it also doesn't really include a comprehensive overview of the involved conventions (nicer word for hard-wired mechanisms that come with the SharePoint implementation of the Workflow host).

So, what is there to cover? The workflow implementation in SharePoint builds on a few concepts. To start with, a workflow can be associated with either a list, content type, or a content type in a specific list. Also, by convention, every time a workflow is associated, one list needs to be linked that will hold the workflow tasks, and another list that will hold the workflow history. This is implemented in a standard page which is called the “Attachment form”.
 
  Picture Attachment Form

The form that follows directly after the Attachment form is the “Association form”, in which the default values for the workflow should be set. The Association form is the first (out of a total of five types of forms) that needs to be implemented. This involves retrieving the data that was entered by the user in the Attachment form, presenting the form to the user and then saving the user input once again.
 

  Picture
Association Form
 
When a user then afterwards selects a workflow to be run on a specific list item, the SharePoint workflow implementation will bring up the "Instantiation form" (sometimes also called Initiation form). It usually resembles the Association form, but can, of course, be entirely different. Also, it's important to know here that workflows can be started automatically (e.g. on upload of a document), in which case the Initiation form will not be displayed.
 

  Picture
Instantiation Form
 
Then, you would typically have different "Task forms" for the various tasks that are part of your workflow. This is where one usually realizes that all of this is going to be a bit more tricky than you'd hope for, as there is no aspx page to be specified for the task edit form, as is the case with the previous two forms.
 
Let's look at how the standard InfoPath-based workflow solution in SharePoint does it ...here too, aspx pages (NOT InfoPath forms!) are specified in the workflow.xml:
 
       AssociationUrl="_layouts/CstWrkflIP.aspx"
       InstantiationUrl="_layouts/IniWrkflIP.aspx"
       ModificationUrl="_layouts/ModWrkflIP.aspx"

 
The SharePoint workflow implementation always uses aspx pages to host the "controls" that were created by building an InfoPath form. (It is a common misunderstanding that the entire InfoPath forms are being used).
 
The first two forms (Association and Instantiation) are easy: we can just define our own aspx pages and reference them here. However, I didn't make a mistake by not listing the aspx form for editing a task above. There is none. One needs to use the Metadata section in the workflow.xml to specify the TaskID_FormURN Elements for the different tasks. When using InfoPath controls the tasks and their corresponding forms are to be linked manually using the TaskType field of each task, which needs to match the enumerator that the FormURN has (e.g. Task0_Form ...another SharePoint convention). However, this only works out of the box with the InfoPath forms implementation.
 
Now, in order to use ASPX forms instead of InfoPath, one either has to use a separate custom content type for each task that needs specific forms (as custom content types allow to specify individual "new, display, and edit" forms). Such a task in the workflow then has to be created using the “CreateTaskWithContentType” activity (referencing the Guid of the respective custom content type). Or, one would have to create separate ascx user controls to be hosted by the aspx page of the standard task, similar to what the implementation for InfoPath controls does. As you might have guessed it, either way comes with its own challenges and work-load.
 
  • Alternative 1: Custom Content Types
    - having a growing number of content types for all the different tasks can easily become a hassle to manage.
    - however, custom content types allow to add transparent storage of workflow data in the task list columns, instead of using the so-called "Extended Properties" collection (name/value pairs)
  • Alternative 2: User Controls
    - to no surprise: all the wiring to load and host these user controls has to be implemented from scratch. You can get an idea of what needs to be done from this post from Jaap Vossers.
    - unlike aspx pages (that usually cannot be worked on in Design mode in Visual Studio, as they can't reference the SharePoint master page), user controls can be designed in Visual Studio with all the nice UI features.


My preferred choice clearly would be to use a custom content type only for the workflow (or at most, one for each custom composite activity, in case those have been developed individually). It certainly has its advantages to have custom list columns to store the workflow data in.
 
There is a way to actually author the forms as aspx pages that allows working in Design mode when building the html, which involves setting the masterpage reference at runtime. However, the ascx user control approach is by far the better way to do it.
 
So, to sum up, we're threatened to have all wheels be reinvented ...except, here comes the SharePoint community cavalry:
 
Robert Shelton has authored a number of really detailed (and working!) screencasts and How To's ...the one document that is absolutely worth reading, in regards to aspx forms, is this 4-part document. From this you can get a hands-on understanding of how all the conventions around wiring up the Association, Instantiation and also the Task Edit forms have to be put together.

 
Picture
TaskEdit Form
 
There’s (only) two potential caveats with his sample: 1) you have to deploy his solution on a subsite (and NOT the rootweb/sitecollection), as otherwise you’ll run into some security issues, and 2) you need to add an “if (!IsPostBack)” to the code in the “Page_Load” method that reads the Association form data into the Instantiation form. Both problems are mentioned and detailed in the comments of their respective posts on Robert’s blog.
 
My recommendation however is to use the new WSS3Workflow solution on Codeplex, that implements the ascx user control approach. I've tested it and it worked well. It's still a bit short on the documentation side of things, but simply open up the Sample project that gets installed and you will get the idea. There are also 3 videos available by now that give some basic information on this solution.
 
Funnily enough though, both in Robert’s sample as well as in the WSS3Workflow sample, only the Extended Properties collection is used to store the task data, even though a custom content type is implemented. It should be noted that the fields (== task list columns) of the custom content type can easily be accessed (e.g. using the Guid of the FieldRefs in the custom content type).
 
Are we done yet? Not quite. I still owe you some info on the other two workflow forms that are part of the SharePoint workflow implementation.
 
The "Modification form" is used in conjunction with the “EnableWorkflowModification” activity: while the workflow is within the scope of the “EventHandlingScope” activity that includes the EnableWorkflowModification activity the link to the Modification form is visible in the Workflow Status page. For this to work, the Guid used in the Modification_GUID_FormURN element must match the modificationID of the EnableWorkflowModification activity. Typically, one would use the Modification form  to modify the workflow, e.g. by adding additional instructions or adding another Approver.
 
Picture
Workflow Status Form
 
Picture
Modification Form 

That leaves us with the last form to look at: the “Bulk Edit Task form”. Obviously, if you’re an approver and you routinely get a lot of documents to approve then it might make sense to shortcut that process and display and edit all tasks that are of the same kind (workflow & association) on the same page, instead of bringing up the Workflow Status form for each task individually. In order to do so, the specific task needs to be identified explicitly as “TaskN_IsBulkActionable” in the Metadata section of the workflow.xml (whereas N is again the TaskType enumerator.
 
Picture
Bulk Task Edit Form
 
It needs to be noted that the WSS3Workflow solution differs a bit, as much as conventions are concerned. E.g. the Menu command for bulk editing tasks can then be found in the “Actions” menu of the list that contains the items for which the workflow has been instantiated, whereas otherwise the InfoPath-based bulk edit mechanism is available in the Actions menu of the Task list.
 
Kudos to Robert Shelton, Chris Predeek and Wouter van Vugt!

Published: Apr-20-09 | 2 Comments | Link to this post