WF 4.0: NullReferenceException in ActivityXamlServices.Load

I tried to dynamically load a workflow XAML from a database. Simple task, I thought, because there is an API for that (the ActivityXamlService class). Unfortunately, when calling ActivityXamlServices.Load I hit these two issues:

  1. When the workflow XAML contains the “x:Class” attribute: A XamlObjectWriterException stating that “Cannot create unknown type ‘{http://schemas.microsoft.com/netfx/2009/xaml/activities}Test.MyActivity’.” (“Test.MyActivity” being the full name of the workflow activity).
  2. When I remove the “x:Class” attribute: A NullReferenceException without any further explanation from inside the ActivityXamlService.GetCompilerSettings method.

Searching this error on the internet showed that there are many possibilities for a NullReferenceException, but in this case, the exception was thrown in the ActivityXamlService.GetCompilerSettings method, and for this case I didn’t find any results.

Well, this sucked! After digging into the source code of ActivityXamlService, I discovered that the code in ActivityXamlService.GetCompilerSettings actually just needs the property “Name” of the DynamicActivity. So if I omit the “x:Class” attribute in the XAML, the Name property is null. I can’t just set the attribute in XAML because the framework would try to load that class and fail. I can’t set the Name property in code because I don’t have an instance of it (that’s the point of using ActivityXamlServices.Load). Solution?

Change the following code:

activity = ActivityXamlServices.Load(reader, settings);

to

var readerType = typeof(ActivityXamlServices).Assembly.GetType("System.Activities.XamlIntegration.DynamicActivityXamlReader");
var dynamicActivityReader = Activator.CreateInstance(readerType, r) as XamlReader;

var xamlObject = XamlServices.Load(dynamicActivityReader);
var dynamicActivity = xamlObject as DynamicActivity;
dynamicActivity.Name = "any.name";

var method = typeof(ActivityXamlServices).GetMethod("Compile", BindingFlags.NonPublic | BindingFlags.Static);
method.Invoke(null, new object[] { dynamicActivity, settings.LocationReferenceEnvironment });               

The code above actually just does the same as the code of ActivityXamlServices.Load, but additionally sets the activity’s name.

This is probably not the most elegant solution. In fact, it feels like I missed some crucial point regardig the usage of ActivityXamlServices.Load. On the other hand, I just could not find another way to get my workflow loaded and additional error messages from inside ActivityXamlServices would have been helpful. It took hours just to figure out what the NullReferenceException meant.

Any thought on this are very welcome.

Freelance full-stack .NET and JS developer and architect. Located near Cologne, Germany.

Leave a Reply

Your email address will not be published. Required fields are marked *