This topic came up in a question asked by Sean Docherty (Ability to cancel a workflow) and I wanted to share some of the solutions that were discussed within in a bit more detail. More specifically, I want to highlight that there are multiple ways of doing the same thing, as pointed out by our own Cassy Freeman.
The Ask
Provide users the ability to cancel a request and in-turn, terminate the workflow and any outstanding tasks.
Solutions
Approach #1: Create a list level workflow that can be triggered and terminate the workflows and then delete the item.
Approach #2: Create a site level workflow that can be called to terminate the workflows and delete the item in any list.
Already we can see the differences, but each will provide us with the same end result. So let’s step through them both.
Approach #1: List Workflow
For this approach we can simply create a new workflow on the list (we will call it Delete Me). Within the workflow there are two actions; Terminate workflow and Delete item.
In the Terminate workflow action we want to stop "All except current workflow". This will terminate any other workflow(s) that are currently in flight for that specific item and in turn, any tasks that are associated to it will be removed as well.
Next we want to delete the item. This can be done using a Delete item action, and you guessed it, we want to delete the "Current item".
Simple, right? So how do we let the user kick it off? We Enable workflow to start from the item menu. This option can be found in the Workflow settings and is a check box. You can even provide a specific name, icon, and reorder it in the menu is desired.
Now that the workflow is setup, users can click on the item and select the workflow:
Once selected, it will take the user to the Start workflow page. I recommend editing the Start Form (under Workflow settings) to provide some context to the user. This can also be used as a last warning to them that they are about to delete the item!
Approach #2: Site Workflow
For this approach we will be creating a site level workflow (we will call it Terminate and Delete). Within this workflow there three actions; Call web service, Build string, Call web service. We want to terminate any workflow, build the XML to delete the item, and then delete the item.
First we want to call the TerminateWorkflowByNameForListItem (if you are looking for it check out {yourURL/_vti_bin/NintexWorkflow/Workflow.asmx). Now we will need to feed it the information about the list, item, and workflow in question. You can also terminate any previous instances, but is not required. So how do we feed in the variables? We can use workflow variables but make them Show on start form and Required for those that are required.
Once these are setup, simply plug them into the web service fields!
With every web service call, I highly recommend testing it with the Run now action with predictable outcomes. This will ensure that your web service is setup properly and the workflow will run properly once triggered.
Next we will want to use the Build string action to create our XML to target the specific item and delete it. There are plenty of reference materials out there on the UpdateListItems method, so I will not go into too much detail here. For now, this is the XML that we want to create:
Once created, save it in our XML variable.
Lastly, we want to call one more web service to perform the deletion of the item. Since we have all the pieces in place (list name and XML) all that is left is to plug them in!
Again, do your testing so that you know it will work!
Once you are satisfied that it is setup and works properly, all that is left is to call it!
But how, you ask!?!?
At this point, you can call it however you want. From any workflow within the site, or even run it manually; the choice is yours! For this example, I have it in a state machine and can be called if the status is changed to "Cancelled".
When an item is created, it goes down both branches; one is for the "main" workflow while the other is to monitor for a "Cancelled" status change. This allows the user to simply change the status to "Cancelled" at any time, even if the workflow is awaiting a response from a task!
Final Thoughts
As always, there is never one way of doing something. There are different approaches and each have their own benefits and drawbacks. For Approach #1, it requires the developer to create the workflow on each list that could possibly need this functionality. On top of that, if there is a larger need to use this across multiple lists, you will soon have many of the same workflows out there... and isn't the main reason we use workflows is to reduce repetitive work? It is, however, extremely simplistic and does not take long to setup. Approach #2 on the other hand, requires some understanding of web services and how to call and construct them; something that a typical user probably does not have. It also requires some forethought on how you are planning on calling it. However, it reduces clutter by allowing any user, from any list within the site to call it; creating re-usability.
I would love to hear your thoughts on how you would approach this and if you had similar experiences and how you decided to approach the issue.
Until Next Time!