November 2009 - Posts
Note: This blog post is written using the .NET framework 4.0 Beta 2
In Windows Workflow Foundation 4 there are a number of “activities” in the designer that aren’t really activities but activity templates. The most obvious of there are the ReceiveAndSendReply and the SendAndReceiveReply in the Messaging section of the toolbox.
If you search for either of these activities you are not going to find them. Their real name is ReceiveAndSendReplyFactory and SendAndReceiveReplyFactory respectively and they aren’t activities but activity templates.
So how to create an activity template?
Quite simply create a class and implement the IActivityTemplateFactory interface. This interface is simple and consists of a single Create function that returns the activity to be added to the workflow. Need to create multiple activities like the messaging activities do? Just wrap them in a Sequence activity and return that.
So what does that look like? Well in the case of the ReceiveAndSendReplyFactory the Create() looks like this according to Reflector:
public Activity Create(DependencyObject target)
{
string str = ActivityDesignerHelper.GenerateUniqueVariableNameForContext(target, "__handle");
Variable<CorrelationHandle> variable = new Variable<CorrelationHandle>
{
Name = str
};
VisualBasicSettings settings = new VisualBasicSettings
{
ImportReferences =
{
new VisualBasicImportReference
{
Assembly = requiredAssemblyName,
Import = requiredNamespace
}
}
};
Receive receive = new Receive
{
OperationName = "Operation1",
ServiceContractName = XName.Get("IService", "http://tempuri.org/"),
CorrelationInitializers =
{
new RequestReplyCorrelationInitializer
{
CorrelationHandle = new VisualBasicValue<CorrelationHandle>
{
ExpressionText = str,
Settings = settings
}
}
}
};
return new Sequence
{
Variables = { variable },
Activities =
{
receive,
new SendReply
{
DisplayName = "SendReplyToReceive",
Request = receive
}
}
};
}
Nice to know what is happening behind the scenes and IActivityTemplateFactory is a nice interface to have when you start creating your own complex activities.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
Tomorrow I will be doing an online presentation about Windows Workflow Foundation 4. The meeting lasts 1 hour and starts at 4PM European time, 3PM UTC or 7AM PST.
The goal is to provide an overview of WF4 and how to get started with it in Visual Studio 2010.
I will be doing the meeting using LiveMeeting and you can register here.
During the meeting I will also be tracking the Twitter hash tag #dmwf4 for additional questions and feedback.
“See” you there tomorrow 
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
Note: This blog post is written using the .NET framework 4.0 Beta 2
I can’t say I am a fan of the way the TryCatch activity is implemented in Windows Workflow Foundation 4.
For starters there is a Finally block where you can add some activities you want to execute. Sounds nice and very much like the try/catch/finally code construct we have in C# or Visual Basic. Except that it behaves in a subtlety different way. With the C# try/catch/finally the finally code will always run, whether you catch the exception or not. In fact you can just use a try/finally and it will work just fine.
With WF4 this is not the case though 
The finally activity will only execute if the try block or one of the catch blocks completes. This means that an exception that is unhandled which bubbles terminating the workflow up will not cause the finally block to execute unless the host application forces it to do so by returning UnhandledExceptionAction.Cancel from the OnUnhandledException instead of UnhandledExceptionAction.Terminate (the default). A subtle difference and one that is likely to bite people because the normal code path is usually to have the try activity to complete normally.
Another issue I have is with the catch blocks and the cause of the exception.
As with a code catch block you get a reference to the exception. However where you normally would use the stack trace to see where the error occurred this is useless in Windows Workflow Foundation. After all that is only going to show you a few methods in the ActivityExecutor and the activity that was executed, not which instance and where in the activity tree. And by default there is no way to get to the offending activity 
Turns out that Darren Headrick created a rather nice way to get to the offending activity through workflow tracking. Quite a nice solution but not entirely obvious and I am sad that a solution like this is needed. Still nice work from Darren though 
public class WhosFaultWasThat : TrackingParticipant
{
public string Name { get; set; }
protected override void Track(TrackingRecord trackingRecord, TimeSpan timeout)
{
if (trackingRecord is FaultPropagationRecord)
{
Name = ((FaultPropagationRecord)trackingRecord).FaultSource.Name;
}
}
}
Besides the FaultSource you also get the Fault and a FaultHandler property which will tell you if there is a TryCatch activity that might handle it. I say might because while you can see that there is a TryCatch you can’t quite see its catch blocks so you don’t know if it will be caught or not.
This neat trick does show one important thing though.
If you want to know what is going on with your workflow and activities you need to use a TrackingParticipant and add it to the Extensions collections. No matter which execution module you choose, WorkflowInvoker, WorkflowApplication or WorkflowServiceHost, they all support this mechanism.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
If you are looking for the demo files from my CodeCamp presentation in the Netherlands you can download the notes here and the complete sample code here. No PowerPoint, after all this was a CodeCamp 
And when my ISP is fully operational again
the demo can be viewed online here.
Enjoy, I enjoyed organizing the CodeCamp and doing this presentation.
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
Note: This blog post is written using the .NET framework 4.0 Beta 2
The whole persistence model has changed quite a but for WF4.
The persistence class out of the box is called SqlWorkflowInstanceStore and as the name suggests it saves workflow data in either SQL Server 2005 or 2008. It is based on the InstanceStore class to if you prefer some other store all you need to do is subclass the InstanceStore and create your own.
So what can we do with the SqlWorkflowInstanceStore?
We can attach it to either a WorkflowApplication or a WorkflowServiceHost and persist workflows when we want. Notice I left out the WorkflowInvoker. This can be used to run only short lived workflows and doesn’t support persistence.
The case of the WorkflowApplication is quite simple.
var instanceStore = new SqlWorkflowInstanceStore(connStr);
WorkflowApplication app = new WorkflowApplication(workflow);
app.InstanceStore = instanceStore;
app.Run();
Okay its a little more involved then that.
First of all you need to create a database to store the workflow state in. There are a couple of SQL files in the “C:\Windows\Microsoft.NET\Framework\v4.0.21006\SQL\en” folder. The two you need are SqlWorkflowInstanceStoreSchema.sql and SqlWorkflowInstanceStoreLogic.sql. I created a batch file to quickly recreate my persistence database like this:
osql -E -S .\sqlexpress -Q "Drop Database WorkflowInstanceStore"
osql -E -S .\sqlexpress -Q "Create Database WorkflowInstanceStore"
osql -E -S .\sqlexpress -d WorkflowInstanceStore -i SqlWorkflowInstanceStoreSchema.sql
osql -E -S .\sqlexpress -d WorkflowInstanceStore -i SqlWorkflowInstanceStoreLogic.sql
So with all this in place we still need to tell the WorkflowApplication when to persist the workflow. There are several ways to to this but one is to use the PersistableIdle callback. This will only fire when an InstanceStore has been provided. Options are to persist and unload the workflow, just unload the workflow or do nothing at all. The callback is just another function so you can make whatever decisions you like.
app.PersistableIdle = e => PersistableIdleAction.Persist;
Another option is to use the Persist activity. This will allow the workflow to decide on extra persistence points regardless of the workflow being idle.
How about the WorkflowServiceHost?
With the WorkflowServiceHost we get a couple of different choices. First of all we can just create a SqlWorkflowInstanceStore and set it like this:
var workflow = new Workflow1();
var baseAddress = new Uri("http://localhost:8080/MyWorkflow");
var host = new WorkflowServiceHost(workflow, baseAddress);
var connStr = @"Data Source=.\sqlexpress;Initial Catalog=WorkflowInstanceStore;Integrated Security=True;Pooling=False";
var instanceStore = new SqlWorkflowInstanceStore(connStr);
host.DurableInstancingOptions.InstanceStore = instanceStore;
host.Open();
Console.WriteLine("Listening...");
Console.ReadLine();
host.Close();
Simple but it doesn’t give us any control over when workflows are persisted. We don’t get quite the same control as with a WorkflowApplication in this case, all we can do is set a few timeout values using the WorkflowIdleBehavior like this:
var workflowIdleBehavior = new WorkflowIdleBehavior();
workflowIdleBehavior.TimeToPersist = TimeSpan.FromSeconds(10);
workflowIdleBehavior.TimeToUnload = TimeSpan.FromMinutes(1);
host.Description.Behaviors.Add(workflowIdleBehavior);
We can’t make any decisions based, just set time the workflow is idle before it is persisted and the same before it is unloaded.
Suppose we want some more control over the way the SqlWorkflowInstanceStore behaves. We can using the SqlWorkflowInstanceStoreBehavior. This is actually the same class as is used through the config file.
var connStr = @"Data Source=.\sqlexpress;Initial Catalog=WorkflowInstanceStore;Integrated Security=True;Pooling=False";
var behavior = new SqlWorkflowInstanceStoreBehavior(connStr);
behavior.InstanceCompletionAction = InstanceCompletionAction.DeleteNothing;
behavior.InstanceLockedExceptionAction = InstanceLockedExceptionAction.AggressiveRetry;
behavior.InstanceEncodingOption = InstanceEncodingOption.None;
host.Description.Behaviors.Add(behavior);
So that is all there is to it?
Not quite there is a little complexity when it comes to using the same SqlWorkflowInstanceStore with multiple WorkflowApplication instances. Note that the WorkflowServiceHost automatically takes care of this so no need to worry about that.
By default a SqlWorkflowInstanceStore will only work with a single WorkflowApplication. If you try to use it with mutiple workflow you can get a InstancePersistenceCommandException with the following message:
SqlWorkflowInstanceStore does not support creating more than one lock owner concurrently. Consider setting InstanceStore.DefaultInstanceOwner to share the store among many applications.
The trick is to set the DefaultInstanceOwner of the SqlWorkflowInstanceStore. The code isn’t hard but not exactly obvious either.
var instanceStore = new SqlWorkflowInstanceStore(connStr);
var instanceHandle = instanceStore.CreateInstanceHandle();
var createOwnerCmd = new CreateWorkflowOwnerCommand();
var view = instanceStore.Execute(instanceHandle, createOwnerCmd, TimeSpan.FromSeconds(30));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
// Do whatever needs to be dome with multiple WorkflowApplications
var deleteOwnerCmd = new DeleteWorkflowOwnerCommand();
instanceStore.Execute(instanceHandle, deleteOwnerCmd, TimeSpan.FromSeconds(30));
The key is the CreateWorkflowOwnerCommand that needs to be executed at the start. And when you use the CreateWorkflowOwnerCommand just make sure not to forget the DeleteWorkflowOwnerCommand otherwise all workflow will remain locked by the owner and can’t be reloaded by another SqlWorkflowInstanceStore
Quite a but more flexible than we had before but, specially with the WorkflowApplication, also quite a bit more work and not always as obvious as I would like it.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
This one bit me today a bit unexpectedly.
I was comparing two Uri’s and was getting unexpected matches between two Uri’s that where quite clearly not the same. Turns out the when comparing Uri’s the Fragment, or anchor or part after the #, is not part of the comparison.
So the following unit test passes even though I would have expected it to fail!
[TestMethod]
public void TestTwoEqualUrisWithDifferentAnchorShouldNotBeEqual()
{
var baseUri = new Uri("http://www.test.com");
var uri1 = new Uri(baseUri, "#anchor1");
var uri2 = new Uri(baseUri, "#anchor2");
Assert.AreEqual(uri1, uri2);
Assert.AreNotEqual(uri1.ToString(), uri2.ToString());
}
Note that when comparing uri1 and uri2 they are equal even though they use two different anchor tags. Comparing the ToString() results does show the difference though. Wasted another bit of time on this piece of trivia 
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
recently I had to send a bunch of identical email messages for the CodeCamp we are organizing. Now there are plenty of ways to do this but I decided to write a little program using C# to send them. And just to make sure I can find the code next year 
var from = new MailAddress("<<your email>>", "<<your name??");
var to = new MailAddress("<<destination address>>", "<<their name>>");
var message = new MailMessage(from, to);
message.Subject = "The subject";
message.Body = "The message body";
message.IsBodyHtml = true;
var host = "smtp.gmail.com";
var client = new SmtpClient(host, 587);
client.EnableSsl = true;
client.Credentials = new NetworkCredential("<<your username>>", "<<your password>>");
client.Send(message);
Easy as that.
Few things to note. I used a different sender address as we wanted all replies to end up in a shared mailbox instead of mine. Worked just fine even though I used my own account details to send.
There is a check on the number of messages send in a short time span. Not sure what the limit is, it seemed something like 100 per minute, but I had to add some sleep time between messages in order to send them all. No big deal but something to keep in mind.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
Als eerste: de sessies voor de CodeCamp 2009 zijn bekend en staan online op http://www.codecamp.nl We denken dat het een erg interessante mix van sessies is, met genoeg sessies voor iedereen om een aantal interessante onderwerpen voor iedereen. De agenda ziet er nu als volgt uit:
09:30 - 10:45
Around .net framework 4.0 in an hour (Ronald Guijt)
ASP.Net - MVC 2.0 (Sander Gerz)
Windows Mobile en het werken met data (Arjan van Huizen)
11:00 - 12:15
ADO.NET EF 4.0 (Kurt Claeys)
SharePoint Nightmares (Marianne van Wanrooij)
iPhone development met jQTouch (Maurice de Beijer)
13:15 - 14.30
VSTO 2010 met Office 2010 (Hassan Fadili)
Modulaire Silverlight apps met Prism (Timmy Kokke)
Microsoft Surface Development (Freena Eijffinger & Dennis Vroegop)
14:45 - 16:00
VSTS 2010 (Pieter de Bruijn)
Windows Identity Foundation (Michiel van Otegem)
SQL Azure (Marcel Meijer)
Naast deze sessies hebben we ook nog de OpenSpace sessies. Daar hebben we geen agenda voor maar dat ligt nu eenmaal in de aard van een OpenSpace gebeuren. In het kort komt het neer op het volgende: als je iets hebt waar je graag met een aantal mensen over wilt discussieren, schrijf je dat 's ochtends op een flip-over. Mochten mensen dat interessant vinden, dan kunnen ze een stem uitbrengen op dat onderwerp. In de lunchtijd (van 12:15 - 13:15) is dan de keuze aan de mensen waar ze heen gaan en aan welke discussie ze mee willen gaan doen. Heeft jouw sessie genoeg stemmen dan komen de mensen vanzelf wel naar je toe, zo niet: dan is je sessie blijkbaar niet interessant voor een grote groep. Het idee is dat we een aantal van deze sessies tegelijkertijd hebben zodat mensen kunnen kiezen wat ze doen. De inhoud van de lunch sessies laten we dus volledig aan de bezoekers over!
Denk eens na over sessies of onderwerpen en discussieer mee met je mede-ontwikkelaars over jouw favoriete onderwerp!
Ik kan haast niet wachten tot het 21 november is..