Ever since the release of EPiServer CMS 5, workflow within EPiServer CMS has been based on Microsoft’s Workflow Foundation. Out of the box EpiServer comes with four pre-configured workflows:
- Sequential Approval
- Parallel Approval
- Request For Feedback
- Ready For Translation
Issues with the approval workflows
The sequential and parallel approval workflows are designed to regulate the publishing of pages within the website. However, there are a couple of features with the out of the box design that could cause issues if you want to use these approval workflows to automatically regulate the publishing of pages on your website.
1. These workflows required that any approvers have to have publish access to that page.
This means that approvers can bypass the workflow system and publish the page before it has gone through all it’s stages.
2. The workflows do not check if there is an existing workflow instance for that page before creating a new one.
If a page is set to “Not Approved” a task is created for the original editor which allows them to send the workflow back to the approvers. If an edit is done, this workflow can be associated with the new version of the page. The trouble comes if you have set the workflow to be created by one of the events involved with the editing process (either Save or Ready to Publish) then a new instance of the workflow will be created, leading to multiple instances of the workflow for a page.
Getting workflows to work
Getting the approval workflows to work in a more logical way is not easy because of the highly bound way that EPiServer built the workflow system.
Step 1. New Approval Service
To remove the requirement for an approver to have publish access, the
HasReadAndPublishRights method of the
EPiServer.WorkflowFoundation.Workflows.ApprovalService class needs to be modified. Although the method is public it is not virtual, and because of how it is accessed internally and externally, inheriting from it and marking the new method as
new will not work. The only solution is to copy the source into a replacement class and edit the
HasReadAndPublishRights method to remove the checks for Publish access.
EPiServer.Config will need to be updated replacing the
<externalService> entry for the EPiServer
ApprovalService with your new one.
Step 2. Replacing the workflow dialogs
Unfortunately this is only the start of the issues. There is a tight coupling between the
ApprovalService class and the controls used to display the task forms. To get around this, a number of ascx files need to be copied from the CMS/edit folder into a folder in your web project:
To redirect calls from the original controls to the new ones we can use the EPiServer virtual path mapping provider.
<add showInFileManager="false" virtualName="WFMapping" virtualPath="~/episerver/CMS"
The source of WorkflowApprovalStart.ascx and WorkflowApprovalEvent.ascx both need copying into new class files and the controls edited to use them. This is so they can be pointed to use the new
The WorkflowTaskControl.ascx source code needs to be copied and the
TryLoadControlFromAttribute method needs modifying. This method looks at an workflow activity and loads the control specified by it’s ActivityPlugIn attribute. Unfortunately this URL will point to the original controls not your new ones. Modifying this method to use the VirtualPathMappings configuration settings to look up the new control URL and use this to load the new control.
The WorkflowHistoryList.ascx and WorkflowApprovalVersion.ascx can be left as is as they are only there to make WorkflowTaskControl.ascx compile.
Step 3. Only one workflow instance per page
As described above there are a few scenarios that could lead to a page having multiple running workflow instances.
Both of the approval workflows use an
IsValidParameter method to check if the workflow has the right parameter settings to be assigned to approvers or, if not, just closed. Modifying this to check if there is a running workflow instance, other than the current one, already exists and returning false if it does. This stops multiple running workflow instances existing for the same page.