I've an application that host WF4.5 workflow in IIS using WorkflowServiceHost, WorkflowServiceHostFactory and WorkflowHostingEndpoint.
The workflow is defined by VS 2013 in a .xaml file. In the workflow a have a custom activity for receive input data from a user. Get that using CreateBookmark and the callback for Resume.
My problem is: The first activity execute and the workflow instance goes to idle, persist and unload. After resuming the first bookmark the second activity execute an the workflow instance goes to only idle. Thus only the first activity make workflow instance to persist and unload.
To verify that my host implementation works, i used a Delay activity and everything works.
My custom activity:
public sealed class WaitForResponse<TResult> : NativeActivity<TResult>
{
public string ResponseName { get; set; }
protected override bool CanInduceIdle
{
get
{
return true;
}
}
protected override void Execute(NativeActivityContext context)
{
context.CreateBookmark(this.ResponseName, new BookmarkCallback(this.ReceivedResponse));
}
protected void ReceivedResponse(NativeActivityContext context, Bookmark bookmark, object obj)
{
this.Result.Set(context, (TResult)obj);
}
}
IWorkflowCreation client = new ChannelFactory<IWorkflowCreation>(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress("net.pipe://localhost/workflowCreationEndpoint")).CreateChannel();
//create an instance
Guid id = client.Create(null);
// Resume
client.ResumeBookmark(id, "1", "Message 1");
After a conclusion of a bookmarked activity(createbookmark/resume) the instance no more persist/unload.
In other words, only the first bookmarked activity set instance do unload. And yes , I've set TimeToPersist/TimeToUnload.
Here is the tracking status of the instance:
Started, Idle, Persisted, Unloaded, Resumed, Idle, Idle, Idle, Idle, Idle, Completed, Deleted.
I created a sample solution that demonstrates the problem. Sample for download.
I really appreciate if someone could help me. Thank you for any help!
Thank you for any help!
A workflow instance will persist at runtime only when it enters a persistable state, either when it goes idle or Persist activity is used.
WorkflowServiceHost
doesn't give you much control over when workflow instance is persisted but you can configure the when. Check How to: Configure Idle Behavior with WorkflowServiceHost.
Quoting:
Workflows go idle when they encounter a bookmark that must be resumed
by some external stimulus, for example when the workflow instance is
waiting for a message to be delivered using a Receive activity.
WorkflowIdleBehavior is a behavior that allows you to specify the time
between when a service instance goes idle and when the instance is
persisted or unloaded. It contains two properties that enable you to
set these time spans. TimeToPersist specifies the time span between
when a workflow service instance goes idle and when the workflow
service instance is persisted. TimeToUnload specifies the time span
between when a workflow service instance goes idle and when the
workflow service instance is unloaded, where unload means persisting
the instance to the instance store and removing it from memory
<behaviors>
<serviceBehaviors>
<behavior name="">
<workflowIdle timeToUnload="0:05:0" timeToPersist="0:04:0"/>
</behavior>
</serviceBehaviors>
</behaviors>
Note that the default value for timeToPersist is MaxValue. So, although your custom activity goes idle because you're creating a bookmark, it never persists (at least for a long!! time).
EDIT:
After playing with your sample and reading some documentation, what you need to do is to call SendResponse within OnResolveBookmark
protected override Bookmark OnResolveBookmark(object[] inputs, OperationContext operationContext, WorkflowHostingResponseContext responseContext, out object value)
{
Bookmark bookmark = null;
value = null;
if (operationContext.IncomingMessageHeaders.Action.EndsWith("ResumeBookmark"))
{
//bookmark name supplied by client as input to IWorkflowCreation.ResumeBookmark
bookmark = new Bookmark((string)inputs[1]);
//value supplied by client as argument to IWorkflowCreation.ResumeBookmark
value = (string)inputs[2];
// !!! Call it here, for example. !!!
responseContext.SendResponse(null, null);
}
else
{
throw new NotImplementedException(operationContext.IncomingMessageHeaders.Action);
}
return bookmark;
}
This is briefly pointed out here:
Override OnResolveBookmark to manually extract the bookmark from the
incoming message. If you override this method, you must invoke
SendResponse in its body so as to respond to the message sent to the
WorkflowHostingEndpoint
I don't known if this can be seen as a bug or not. The workflow engine seems to get into a state where, although it goes idle because you're giving it a bookmark, it doesn't really known it because a response warning about it is never sent.