Archive for November, 2008

Struggling with DelayActivity in SharePoint (WSS)

November 23, 2008

I want to describe some issues that I came across when I developed SharePoint workflows with the DelayActivity.

Note: Always install WSS SP 1. Without it I think you will not be able to make the delayactivity work.

Imagine following simple scenario:
A task should be created for a user. When the user does not finish the task in defined time then another user has to accomplish the task instead of him. Here is a workflow that implements the scenario:

branch12

branch22

Here are the catches:

1.Imagine that you want to read data from custom configuration secion from web.config in the createTask2_methodinvoking. e.g. You have defined the login name of user for that the task should be created in the web.config. Then you probably get a NullReference exception.(fill in exception text) This is because the workflow is dehydrated (or whatever) by the process owstimer.exe. This is the Windows SharePoint Timer service, that checks the sleeping workflows. So this service does not know where the sharepoint web.config is and so the custom section is not created. You can avoid it by getting the config section in OnWorkflowActivated method and assign it to a public property of the workflow.
2.Avoided the first problem you will immediately run into a deserialization error, when the owstimer.exe respawns the workflow. This is because the custom section is not marked with the attribute [Serializable] by default. So you must add this attribute to your custom section and also to all subsections in your custom section.
3.Promote the TimeoutDuration in the DelayActivity to a bindable property. The owstimer.exe wil respawn the default value (in this example 5 minutes) unless you bind it to a property.
Wrong way:
delayactivitypropertieswrong
Good way:

delayactivitypropertiesgood

4.Do the same thing as in point
3. with your taskIds in createTaskActivity. Bind it to a property and assign a new unique Guid in CreateTaskMethodInvoking event.
5.You can also get following cryptic  error:

System.Runtime.Serialization.SerializationException: The object with ID 439 implements the IObjectReference interface for which all dependencies cannot be resolved. The likely cause is two instances of IObjectReference that have a mutual dependency on each other.     at System.Runtime.Serialization.ObjectManager.GetCompletionInfo(FixupHolder fixup, ObjectHolder& holder, Object& member, Boolean bThrowIfMissing)     at System.Runtime.Serialization.ObjectManager.CompleteObject(ObjectHolder holder, Boolean bObjectFullyComplete)     at System.Runtime.Serialization.ObjectManager.DoFixups()     at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage.methodCallMessage)     at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)     at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)     at System.Workflow.ComponentModel.Activity.Load(Stream stream, Activity outerActivity, IFormatter formatter)     at System.Workflow.ComponentModel.Activity.Load(Stream stream, Activity outerActivity)     at System.Workflow.Runtime.Hosting.WorkflowPersistenceService.RestoreFromDefaultSerializedForm(Byte[] activityBytes, Activity outerActivity)     at Microsoft.SharePoint.Workflow.SPWinOePersistenceService.LoadWorkflowInstanceState(Guid instanceId)   at System.Workflow.Runtime.WorkflowRuntime.InitializeExecutor(Guid instanceId, CreationContext context, WorkflowExecutor executor, WorkflowInstance workflowInstance)     at System.Workflow.Runtime.WorkflowRuntime.Load(Guid key, CreationContext context, WorkflowInstance workflowInstance)     at System.Workflow.Runtime.WorkflowRuntime.GetWorkflow(Guid instanceId)     at Microsoft.SharePoint.Workflow.SPWinOeHostServices.Send(SPWinOeWorkflow winoeworkflow, SPWorkflowEvent e)     at Microsoft.SharePoint.Workflow.SPWinOeEngine.RunWorkflow(Guid trackingId, SPWorkflowHostService host, SPWorkflow workflow, Collection`1 events, TimeSpan timeOut)

You need to restart the owstimer.exe service using control panel -> services. This is caused by this: The w3wp process runs another (newer) version of the workflow dll than the owstimer.exe. Then happens an error when dehydrating the workflow state.
6. A „nice“ feature of WWF in SP is also that the workflow state says „Running“ state even when an error occurs. The only way to find that anything went wrong is to check SharePoint log file for workflow infrastructure errors.