Wednesday, April 2, 2014

Debugging workflows in EPiServer Commerce 7.6

Today I've had the pleasure of debugging workflows in EPiServer Commerce. In the project I'm working on, we've downloaded the Workflow activities samles and customized them to meet our customers need. This worked fine until we upgraded our project to EPiServer 7.6, but after the upgrade strange things started happening.

The first error that occured was a compile error in the Mediachase.Commerce.Workflow project:

Could not load file or assembly 'EPiServer.Framework, Version=7.5.394.2

Now, that's strange, seeing as I just upgraded the project to EPiServer 7.6 and there exists no references to EPiServer 7.5 anywhere. Trying to find any clues, I ran across the following error when trying to open a couple of the workflows:

Error loading workflow. Could not deserialize object. The type '' could not be resolved.

Now, this error was a lot easier to debug than the first one! Clearly, there's something wrong with the namespace in the workflow as the ProcessPaymentActivity is one of the activities in the Mediachase.Commerce.Workflow.Activities project. Taking a look at the .xoml of the workflow this is what I found:

<SequentialWorkflowActivity x:Class="Mediachase.Commerce.Workflow.CartCheckoutWorkflow" x:Name="CartCheckoutWorkflow" xmlns:ns0="clr-namespace:Mediachase.Commerce.Workflow.Activities;Assembly=Mediachase.Commerce.Workflow.Activities, Version=, Culture=neutral, PublicKeyToken=null" xmlns:ns1="" xmlns:x="" xmlns="">
 <IfElseActivity x:Name="ifElseActivity1">
  <IfElseBranchActivity x:Name="ifElseBranchActivity1">
    <CodeCondition Condition="RunProcessPayment" />
    <ns1:ProcessPaymentActivity Warnings="{x:Null}" OrderGroup="{ActivityBind CartCheckoutWorkflow,Path=OrderGroup}" Payment="{x:Null}" x:Name="processPaymentActivity1" />
  <ns0:CalculateTotalsActivity x:Name="calculateTotalsActivity1" OrderGroup="{ActivityBind CartCheckoutWorkflow,Path=OrderGroup}" Warnings="{x:Null}" />
<ns1:RecordPromotionUsageActivity UsageStatus="Used" Warnings="{x:Null}" OrderGroup="{ActivityBind CartCheckoutWorkflow,Path=OrderGroup}" x:Name="recordPromotionUsageActivity1" />

If you take a look at the reference to ProcessPaymentActivity on line 7, you can see that it's prefixed with ns1, meaning it's in the namespace declared by xmls:ns1 attribute on line 1. If you've been paying attention, you will also see that the namespace "" is, in fact, the namespace in the error message we received. Change the namespace, and voilá! The compile error complaining about EPiServer.Framework 7.5 not being referenced disappears and you'll be able to open your workflows again:

Old namespace:

New namespace (this might be different in your project):
xmlns:ns1="clr-namespace:Mediachase.Commerce.Workflow.Activities;Assembly=Mediachase.Commerce.Workflow.Activities, Version=, Culture=neutral, PublicKeyToken=null" xmlns:ns1="clr-namespace:Mediachase.Commerce.Workflow.Activities.Cart;Assembly=Mediachase.Commerce.Workflow.Activities, Version=, Culture=neutral, PublicKeyToken=null"

While debugging the workflows, I also ran across another bug worth mentioning. Somewhere along the way I received the following error when trying to open a workflow:

Error loading workflow. Could not deserialize object. The type 'Mediachase.Commerce.WorkflowActivities.Cart.GetFulfillmentWarehouseActivity' could not be resolved.

First thing I checked was of course if the namespace was correct, as that had been my previous issue. The namespace was indeed correct, so I had to keep on looking. The problem turned out to be that the namespace declaration was missing the assembly version number.

Incorrect declaration without assembly version:
xmlns:ns1="clr-namespace:Mediachase.Commerce.Workflow.Activities.Cart;Assembly=Mediachase.Commerce.Workflow.Activities, Culture=neutral, PublicKeyToken=null"

Correct declaration containing assembly version:
xmlns:ns1="clr-namespace:Mediachase.Commerce.Workflow.Activities.Cart;Assembly=Mediachase.Commerce.Workflow.Activities, Version=, Culture=neutral, PublicKeyToken=null"

Hopefully this will save you some time debugging your workflows!