Workflow walkthrough

A walkthrough of the workflow, data and view that constitute an editor

A CMS Console application typically define new data schemas, has a tree structure enabling users to navigate data and invoke commands and logic that control commands and UI flow and UI definition. Below we will focus on the "Edit" workflow in the demo and explain what atrifacts are in play.

The data schema

If you open the C1 CMSWorkflowDemo project and examine the file /DataTypes/IProduct.cs you will see a data type definition. They are defined as interfaces that inherit from IData and attributes on the interface and its members define meta data for the type.

The tree for navigation

If you open the web project and examine the file /App_Data/Composite/TreeDefinitions/C1WorkflowDemoTree.xml you will see the how the thee in the CMS Console is defined. It has a ‘static’ root folder which contain IProductCategory elements and below these you will find IProduct elements. A filter on the products ensure that the products are listed below the category they belong to.

The tree definition contains a number of actions – in this sample they are all WorkflowAction elements, meaning that a Workflow Foundation workflow will be invoked as the action. The WorkflowType attribute on the element define the type name for the workflow. If you examine the product action labeled "Edit" you will find that it invoke C1 CMSWorkflowDemo.Workflows.EditProductWorkflow.

The workflow and form

If you open the C1 CMSWorkflowDemo project and examine the file /Workflows/EditProductWorkflow.cs you will see a state machine workflow. This is a fairly simple workflow which will initialize and then go to "editStateActivity" state where Save and Cancel events are the only triggers. When the Save event is fired the workflow will validate data and on success transition to "saveStateActivity", save data and then transition back to the "editStateActivity" awaiting another Save event. A global Cancel event is handled which will transition the workflow to its final state.

If you dive into the workflows activities in more detail, you will find that the initializeStateActivity is reading a property set on the workflow – this.EntityToken – which is populated by C1 CMS when the workflow is created. This is the element from the tree on which the "Edit" command was executed, and in this case we expect this to be an IProduct data element. The entire data object is retrieved and stored in the workflows Bindings object – a object collection that is shared between the workflow code and the UI.

Once the initialization is completed the workflow transitions to editStateActivity which just contains a single sub activity -  a custom C1 CMS activity named editDocumentFormActivity. This present the user with a UI, where the view is defined in an external XML file located in ~/App_Data/Composite/Forms/C1WorkflowDemo/EditProduct.xml and the data is defined in the workflows Bindings, which was prepared in the initialization described above.

If you try to edit one of the sample products and compare the UI you get with the content of the EditProduct.xml file you should be able to see the relation between the XML and the UI.

When the workflow is in the editStateActivity it will wait for a Save event (or a global cancel event) for the workflow state to change. If you examine the workflow in VisualStudio you can see the Save event trigger as editEventDrivenActivity_Save located in editStateActivity. If you open up this event driven activity you will see that it – after receiving the external Save event – will execute some validation code and then branch according to the validation. The left branch (validation went well) will transition to the saveStateActivity, while the right branch will display a validation error message and then transition back to editStateActivity (without saving any data).

When the workflow transitions to the saveStateActivity a single code activity is executed – the code here stores the product data object received from the Bindings, refresh the tree and specify to the client that the save went well (turning off the save button in the UI). When the product is saved and the UI has been updated accordingly the workflow transitions back to the editStateActivity, waiting for the next time the user press the Save button.

At some point the user closes the document editor tab or the entire browser window and a Cancel event if fired on the workflow – in this case the workflow execute no custom code as part of the cancel event and the workflow and it’s state is unloaded and removed.

If you right click the designer and select View code you get the custom code behind the workflow. There are two points worth noting which we did not cover above:

  • The workflow class inherit from Composite.Workflow.Activities.FormsWorkflow – this is a base class which ensure that all the C1 CMS bells and whistles are available to you
  • The workflow class has an attribute attached - AllowPersistingWorkflow(WorkflowPersistingType.Idle) – which instruct C1 CMS to serialize the workflow (typically to disk) whenever it’s idle (waiting for an event). This attribute ensure that the workflow will live on, even if the ASP.NET application restarts etc. but it also require that all objects you put in the workflows Bindings can be serialized.