For a good long amount of time, workflows have been an essential part of Episerver Commerce (and even before that, Mediachase eCF). Once you get into order system, you just can’t escape workflows – because you need them. They handle many – if not all things, from validating items, checking inventories (to make sure that you are not selling something out-of-stock, or just discontinued (think of Galaxy Note 7, poor little shiny phone)), applying promotions, calculating taxes, process payments, and finally adjust inventories (yay, a customer places an order, let’s ship to him as soon as possible, firstly allocate the goods for him). And workflows are even required by later processing – when you complete the shipments (another happy customer!), or when you issue a return or an exchange (well, let’s keep the customer still happy).
Initially workflows were built on Windows Workflow Foundation – and that means XOML, XOML everywhere
And it is not the best way to do thing. You had to configure your workflows in less-than-easy to read XML (I found the designer provided by Visual Studio to be almost useless), and debugging was a nightmare. Episerver provides the workflows project as open source so you can customize the workflows yourself, but that barely helps. And having the workflow project in your solution comes with an infamous issue: If the Commerce version was built with Framework version x.xx, then when you upgrades your Framework version x.xy, MsBuild fails to build your workflows because of some stupid tasks do not take the assembly binding redirects in web.config into account.
Commerce 9 came with an essential change for workflows – the dependencies on WF were removed. The registration and execution of workflows are now done by an engine made entirely by Episerver. XOML is gone (YAY). Workflows – which now named “ActivityFlow” – are registered by code and are much easier to read and understand. It’s an improvement, yes, but there are still something not perfect!
First, it’s not that easy to follow the code contains a call to a workflow. When you see a call to CartValidate, you might want to see what it does. The only “easy” way to see that is to include the Workflow project from Episerver (which is open source) in your solution. However, this is not always up-to-date (Episerver does not release the Workflow project for every version, although there is not always update in that project), and it’s not a simple to navigate to the workflow code. F12 will not work – you will have to use Search functionalities. What is worse, is that if you want to modify a workflow – for example if you are selling digital stuffs and don’t really care about shipping or inventories – you will have to customize the workflows to remove/skip those steps (aka activities). However, that does mean you will have to either a) include the workflow project in your solution, and modify it, or b) override the default workflows with your owns. The former is of course infamous and will be problematic when Episerver releases a new version of workflow and things were changed. The former is still less than hassle free, even when the registration of workflows was greatly improved with Commerce 9.
All in all – workflow was a solution to customize your process, but it’s far from perfect and less than easy to use. And I understand why many of you do not like workflows. But you still have to use it, because it was the only choice.
It’s no longer. In Commerce 9.23, you have a new option: to call APIs directly. The code which was once inside the activities are now extracted to some lean APIs which can be called without workflow at all. For example, this code will replace the call to CartPrepare:
var validationIssues = new Dictionary<ILineItem, List<ValidationIssue>>(); cart.ValidateOrRemoveLineItems((item, issue) => validationIssues.AddValidationIssues(item, issue), _lineItemValidator); cart.UpdatePlacedPriceOrRemoveLineItems(_customerContext.GetContactById(cart.CustomerId), (item, issue) => validationIssues.AddValidationIssues(item, issue), _placedPriceProcessor); cart.UpdateInventoryOrRemoveLineItems((item, issue) => validationIssues.AddValidationIssues(item, issue), _inventoryProcessor); cart.ApplyDiscounts(_promotionEngine, new PromotionEngineSettings());
Yeah, it’s 5 lines of code, compared to one line, but here you can understand what it does: it checks if there is unavailable items in the cart and remove them. It also updates the prices and remove items without valid prices. It also check the inventories and remove items without stock. Finally it applies promotions to the cart. If you don’t want any of those steps, such as checking inventories, you can simply remove that line and no one, even me, will ever complain! If you have custom processing, you can add it here also.
Those are extension methods for IOrderGroup, so you’ll need to move to the new abstraction APIs to use them. Also ApplyDiscounts only works for the new promotion system. But they are the way forward – you should be using both of them. If you are not, then I highly recommend to move as soon as you have chance.
QuickSilver 2+ was updated to remove workflows entirely, so if you want to see how non-workflow code works in action, check it out at https://github.com/episerver/Quicksilver
And now you can finally hate workflows!
Nice work commerce team!