Saturday, April 28, 2007

Microsoft has gone to great lengths to keep you from touching your instance directly, forcing you to always use the workflowinstance class to manipulate your workflow from the outside. They have done this to make sure the integrity of the system is maintained. It is however, a major pain in the ass. ;-)
I have been looking into solving a serious deficiency of windows workflow foundation: updating current workflows in your database. Microsoft does not have a good story on that one, and the WF architecture seems to be designed to make it as hard as possible to actually pull off! One approach to do this, would be to get to your instance, use reflection to get to private and public fields and create your new type, setting those fields as you go. Therefor, I have been looking into getting to my persisted instance.

Please be very careful with the following technique. Do not use it lightly, because it does allow you to do things that will break the integrity. It _will_ get you into trouble, if you do not watch out.


We are going to fetch a persisted workflow, but do not want the workflow runtime interfering. So:

Database db = DatabaseFactory.CreateDatabase("##Your database##");
byte[] act = (byte[])db.ExecuteScalar(CommandType.Text,
"select state from InstanceState where uidInstanceID = '## the guid you are interested in ##'");

This will directly query your database for some guid. (I am using Entlib 3.0 here).
The byte array returned is formatted with the binaryformatter. To be able to serialize activities, the WF-team does not use the Serializable attribute, but uses surrogates. A surrogate is a class that has intimate knowledge on how to serialize a certain type. Looking at the class ActivitySurrogate, you will notice that they have quite a bit going on there. Most important seems to be the private sealed class ActivitySurrogateRef, which defines fields like these:

[NonSerialized]
private Activity cachedActivity;
[NonSerialized]
private Activity cachedDefinitionActivity;
[OptionalField]
private EventHandler disposed;
private string id = string.Empty;
[NonSerialized]
private int lastPosition;
[OptionalField]
private object memberData;
[OptionalField]
private object[] memberDatas;
[OptionalField]
private string[] memberNames;
[OptionalField]
private string rulesMarkup;
[OptionalField]
private Type type;
[OptionalField]
private string workflowChanges;
[OptionalField]
private Guid workflowChangeVersion = Guid.Empty;
[OptionalField]
private string workflowMarkup;

So, it is clear our binaryformatter is going to have to reuse this logic. Thankfully, we can use the ActivitySurrogateSelector. This selector has logic that allows it to select the correct surrogate for each type. We set it like this:

BinaryFormatter formatter = new BinaryFormatter();
formatter.SurrogateSelector = ActivitySurrogateSelector.Default;

Now it is time to deserialize our byte array. However, it is zipped!! So, let's unzip it:

MemoryStream stream = new MemoryStream(act);
stream.Position = 0;
using (GZipStream stream2 = new GZipStream(stream, CompressionMode.Decompress, true))
{ // here we can finally deserialize.  }

Inside that using-statement, we will deserialize. Here is the line that does the magic:

T activity = (T)Activity.Load(stream2, workflowRuntime.CreateWorkflow(typeof(T)).GetWorkflowDefinition(), formatter);

The 'T' is the type of your workflow.
I am using the static Load functionality of Activity to load. We first pass in our unzipped stream (stream2) and then we have to pass the workflowdefinition of the type we are deserializing. Finally, we are using our own formatter, with the activity surrogate attached.

Obviously, the use of the workflowruntime to get to the workflowdefinition is not pretty. Ugly even. However, I have not been able to circumvent it. Passing a null, will result in serializationexceptions.
I will update this post if I find a better way. Please leave a comment if you know of one!

I can imagine that it is useful to be able to get to your instance directly. For now, the only way to get to it, seems to be when they have to release it to the persistence store.

I hope this helps someone!

Saturday, April 28, 2007 5:43:52 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Wednesday, April 11, 2007

My project is migrating a big (very big) winform application to a WPF (using Xbap) application. At this point, only the front-end is touched. The team will eventually evolve into migrating the data-driven procedural backend to a process-centered, domain-driven, WF (Workflow foundation) managed solution.

For this, we are looking for a few experienced C# developers. Obviously, WPF knowledge is a big plus. The project will last for quite a few months. When you walk away, you will have a deep understanding of WPF, CAB and WF.

If this sounds like your cup of tea, please leave a comment or mail me directly. The project is based in The Hague.

Wednesday, April 11, 2007 8:17:14 PM (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
 Tuesday, April 10, 2007

I'm also heading up a team that will be migrating existing businessprocesses to a workflow proces layer. It's exciting, because workflow foundation (WF) allows me to model an entire proces, instead of building small pieces and connecting them in code. This offers superior insight into the real businessproces and thus gives flexibility and power because for the first time, I can really sit down with an analist and explain 'code'. (our UML diagrams are outdated ;-) ). Because we then have a common understanding of the proces, we can feel at ease when modifying it.

Currently I'm working on having the workflow determine the 'actions' that a user (or machine) can perform in some state. WF has the ability to show the possible state transitions and that seems to be the logical piece of information I need to query and present to our client-side code (which well then enable/disable certain commands in the screens). However, it is completely useless because of two things:
1. it does not take into account the role a user is in
2. it will just display the possible transitions, but not the HandleExternalEventActivities (HEEA) that lead to them.

Therefor, I have build my own query. I'm aware that I've probably overlooked some hidden away funtionality, but until then, my code will do perfectly fine!

Given a workflow instance, I will first retrieve the waiting queue's. Then I will iterate the queueInfo objects. In my case, I will only use HEEA activities to handle the queue's, your workflow might differ. I will find that HEEA using the GetActivityByName method. Then I will check if it has roles assigned to it. I will simply check if the given role is in that array.
Next, I will have to lookup the correlationtoken, that might be used. If it is, I'm most interested in the correlationproperty. I will put that combination into my own struct (ProcesCommando). Add it to the list and return it!

ReadOnlyCollection<WorkflowQueueInfo> queues = instance.GetWorkflowQueueData();
foreach(WorkflowQueueInfo info in queues)
{
if(info.QueueName.Equals("SetStateQueue"))
{
continue;
}
else
{
foreach(string subscribedActivity in info.SubscribedActivityNames)
{
HandleExternalEventActivity heea =
instance.GetWorkflowDefinition().GetActivityByName(subscribedActivity) as HandleExternalEventActivity;

Debug.Assert(heea != null,
"Currently only expecting HandleExternalEventActivities");

#region check roles
if(heea.Roles != null)
{
// there are roles defined, so we need to check if the given role is included

bool inRole = false;
// TODO: use predicate
foreach (WorkflowRole workflowRole in heea.Roles)
{
if (workflowRole.Name.Equals(role.Name))
{
inRole = true;
break;
}
}

if (!inRole)
continue; // next subscribed activity.

// apparently the webworkflowrole does not implement equals and gethashcode correctly, so we can't do a 'contains'
// if(!heea.Roles.Contains(role))
// {
// // it does not, so this subscribed activity should never be executed
// continue;
// }
}
#endregion

#region possible correlation
string correlatie = String.Empty;
if (heea.CorrelationToken != null)
{
// there is a correlationtoken, so let's get the correlationproperty

EventQueueName queuename = info.QueueName as EventQueueName;
CorrelationProperty[] corProps = queuename.GetCorrelationValues();

Debug.Assert(corProps.Length == 1,
"Currently expecting exactly one correlation value");
correlatie = corProps[0].Value.ToString();
}

#endregion
ProcesCommands.Add(new ProcesCommando(heea.EventName, correlatie));
}
}

}
return ProcesCommands;

 

Tuesday, April 10, 2007 7:27:21 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Sunday, March 18, 2007

First off, I've returned from a great 7 weeks holiday in New Zealand. I will not bore you with 1500 pictures, although I am perfectly capable of doing just that. On top of that, 3 hours of film was shot. Yikes. It was just that incredible!

For picking up the blogging slack, i'll share with you guys a mechanism for extending objects with attached properties. Although the technique is well documented, I didn't find any resources online with an example of a checked listbox. I did find a post by Josh Smith about it, but he created the checked listbox using the Checked and Unchecked events, which I don't feel is very 'WPF' like.. Not when you are using WPF! So, let's first look at the problem at hand, and then get on to the solution, which is so simple, it feels like an anti-climax.

We have an ObservableCollection<T> with domainobjects, or in our case simple Strings. We wish to show these in a listbox, and give the user the abiliby to select multiple items using checkboxes. We also provide a button, which will just select all of them. Obviously, we want to be able to get to the checked items.
In the past, I would probably have used checked and unchecked events to keep track of the checked items, or I would have extended my domainobject with a 'IsSelected' property and bind to it. The latter would have made me extremely unhappy, because it would mean my userinterface was invading my domainobject.

An attached property, basically, is a property that belongs to another object, but can be set on any dependency object you choose. So, I will introduce a boolean attached property (for instance: IsGeselecteerd, dutch for IsSelected). Then I create the datatemplate for my objects, with a checkbox in it, and a binding to the attachedproperty:

 

<Window.Resources> <DataTemplate x:Key="lbitems"> <StackPanel Orientation="Horizontal"> <CheckBox Name="checkbox" l:Window1.Geselecteerd="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}, Mode=TwoWay }" /> <Label Content="{Binding}" /> </StackPanel> </DataTemplate> </Window.Resources> <StackPanel> <ListBox Name="lv" ItemsSource="{Binding Path=Lijst}" ItemTemplate="{StaticResource lbitems}"> </ListBox> <Button Click="SelectAll">Select all</Button> <Button Click="LeesUit">show selected items in debug.output</Button> </StackPanel> </Window>

 

The binding of interest is: l:Window1.Geselecteerd="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}, Mode=TwoWay }", on the checkbox.
It means that the IsChecked property of itself (the checkbox) is bound to the property Geselecteerd, which lives on the Window1 class.

That's basically all there is to it. Setting the checkboxes from procedural code is somewhat harder then I would like it to be, but only because I couldn't find an easy way to get to the checkbox from code:

 

foreach(object dataitem in lv.Items) { // get the visual container, belonging to the dataitem ListBoxItem lbitem = (ListBoxItem)lv.ItemContainerGenerator.ContainerFromItem(dataitem); // get to the checkbox CheckBox c = (CheckBox) GeefChildHelper(lbitem, "checkbox"); // set the attached property SetGeselecteerd(c, true); }

Point of interest is the setting of the attached property, which will tell the binding of the checkbox to do the appropriate thing and the Helper method, to get to the checkbox:

 

private object GeefChildHelper(ListBoxItem lbitem, string naam) { Border border = VisualTreeHelper.GetChild(lbitem, 0) as Border; ContentPresenter contentPresenter = VisualTreeHelper.GetChild(border, 0) as ContentPresenter; return lv.ItemTemplate.FindName(naam, contentPresenter); }

Here you see the need to first find a contentpresenter, before the FindName method will work..... That's because apparently that's the thing the template is bound to.

Reading the values is just as easy:

 

foreach(string dataitem in Lijst) { ListBoxItem lbitem = (ListBoxItem)lv.ItemContainerGenerator.ContainerFromItem(dataitem); CheckBox c = (CheckBox)GeefChildHelper(lbitem, "checkbox"); Debug.WriteLine(String.Format("item: {0} is {1}", dataitem, GetGeselecteerd(c).ToString())); }

I hope this sample helps someone!

AttachedList.zip (11.99 KB)
Sunday, March 18, 2007 3:50:37 PM (Romance Standard Time, UTC+01:00)  #    Comments [3]  |  Trackback
 Sunday, November 26, 2006

I encountered a rather annoying reflection exception that caused WPF dead in it's tracks during binding which I thought might be nice to share here.

The problem arises when you bind against a property and WPF (or rather: reflection) can not determine which property you actually mean. This situation can occur when you have a property on a base class and you redefine (using the 'new' keyword) that property on a class that inherits from the base class. Here is some pseudo-code:

 

public class mySpecialisation<T> : myBase { public new T myProperty { get { return (T)base.something; } } } public class myBase { public object myProperty { get { return something;} } }

As you can see, the above situation might be a convenient way to construct your classes. However, it will throw an ugly exception.
The obvious way to work-around this problem, is to make the property on the baseclass private or protected. However, in my case, I needed to get the the property through the baseclass as well. So I renamed the property in the inheritor and got rid of the exception. Kind of disappointing though!

Sunday, November 26, 2006 10:50:50 PM (Romance Standard Time, UTC+01:00)  #    Comments [5]  |  Trackback
 Tuesday, November 21, 2006

Although I love Xaml and the declarative person it makes me want to be, I feel even more strongly about fearless refactoring. If I fear renaming properties or moving types around, I do not refactor. And if I do not refactor regularly, my code begins to smell bad, which is a sure way to get my project featured the one place I do not want it ;-)

So, I want to refactor, but Xaml makes me reluctant to do so. We do not set bindings in code behind, but we declare them (which I think is 'good') in Xaml. Visual Studio doesn't search Xaml files for binding-paths. And so I'm left in the dark about what impact my refactoring will have. Furthermore, binding-errors do not throw exceptions, but fail gracefully, leaving a naive unittest none the wiser.

I've tried to catch the RoutedEvent 'Binding.Error' on a higher level, but it doesn't propagate.
Nor does the LoadedEvent of controls, if the control does not explicitly call some Loaded eventhandler. In this approach I thought I would be able to catch the loaded event of the control while they are being put on the screen and register their binding to be checked later. If all your controls in question do declare a Loaded handler, then you could use something like this:

EventManager.RegisterClassHandler(typeof(Control), Control.LoadedEvent,
(RoutedEventHandler)delegate(object sender, RoutedEventArgs e)
{

   // do your thing, throw an exception to let the unit test fail perhaps!
}, true );

But, like I said, this class handler will only fire if the control is already going to another Loaded event prior to this. Bummer.

Another approach would be to write a visual tree walker and question all the bindings in the screen about their status (a property of BindingExpression). This could be some trouble, but should be very do-able.

I've opted for yet another approach. I was using trusty Reflector to see how bindings work and discovered that binding errors are always shown in the output window. After some searching, it seems that even if you do not have any trace sources declared in your app.config, the visual studio debugger always switches the System.Windows.Data trace to the 'Warning'-level. And the warning level will trace a databinding error of code 35 if a binding is in error!

Well, quite an obvious solution then is to create your own trace-listener class and registering it in the app.config. To get it to work, your unit test will have to do a refresh of the Tracesources to get the traces to work: PresentationTraceSources.Refresh();

The Tracelistener:

public class UnitTestTracer : TraceListener
{
public override void Write(string message)
{
  // throw your exception to make trace fail!
}

public override void WriteLine(string message)
{
  // throw your exception to make trace fail!

}
}

And the app.config:

 

<system.diagnostics>
<sources>
  <source name="System.Windows.Data" switchValue="Warning" >
<listeners>
  <add name="unitTestListener" type="UnittestTestWPF.UnitTestTracer, UnittestTestWPF" />
</listeners>
</source>
</sources>
</system.diagnostics>

 Simple, yet effective. The more I think about it, the more I like the approach!

Tuesday, November 21, 2006 10:02:36 PM (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
 Saturday, November 11, 2006

The reason I haven't been blogging much lately is because I'm now heading up a team of developers that are porting a big Winform application to WPF. It's been a blast until now, but I've been too busy to blog. We're using CAB as a means to decouple logic from presentation (MVC-pattern) and one of my developers has been blogging quite heavily about it here.

Let me go into some more detail on the whole WPF experience. As I said, we are porting the client-side of a big application (about 250 screens). We're doing it as an XBAP (Xaml browser application) to enable us to easily distribute it in our intranet. Although this does force us to install a certificate (to gain full-trust), we're not seeing major drawbacks to this approach.
WPF already decouples presentation from code a great deal more then winforms do, but combining it with MVC does give it a whole new dimension. Setting up a simple screen does mean creating a few more classes then we're used to, so we're looking into using the Guidance Automation Tools (GAT) to speed-up development time.

In my honest opinion, WPF is a truly great technology. It does what it promises, but there are a few drawbacks. First of all, I do feel it's kind of slow. Resizing a screen with a lot going on, definitely feels 'heavy'. So that's a bummer (stay away from drop-shadows, they will kill your performance). Furthermore, we are starting to see some places where XAML is not cutting it. For instance, triggers lack power on the equation and multi-bindings are always &&-nd together. Also, some 'bugs', like always clearing validation-errors after a binding update-to-target.
These are all minor things and we can work-around them. It does mean a very steep learning curve for my new developers.

It was a great feeling, when I saw my designteam checking-in controlstyles and my developers not being hindered at all by their work. All the pieces fell into place and that was quite unlike my previous experiences with winforms.

Saturday, November 11, 2006 11:10:31 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Friday, September 08, 2006

I originally posted this little titbit in the wcf forums, but since lots of people there did not seem to know about it, I'll post it here again:
The framework 3.0 RC1 install will kill your existing .svc mapping, so you will not be able to communicate with IIS hosted WCF services (.svc). Obvious workaround is to add the mapping again manually. This will be fixed in the next RC.

I hope that helps a few people out there!

Friday, September 08, 2006 9:25:26 PM (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback