Prevent Workflow Tasks From Being Deleted

Here’s a simple way to prevent users from deleting their assigned tasks (who would ever want to do that??).

Start by coding an ItemDeleting event receiver that cancels the attempt to delete the task.

If you want to drive your users crazy, you can just set the Status to CancelNoError.
Try it out first before you decide to go that route.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

namespace SameNameSpaceAsTheRestOfYourWorkflow
{
    class PreventWorkflowTaskDelete : SPItemEventReceiver
    {
        ///
        /// Prevent a workflow task from being deleted.
        ///
        ///
        public override void ItemDeleting(SPItemEventProperties properties)
        {
            string errorMessage = string.Empty;
            try
            {
                errorMessage = string.Format("User {0} is not allowed to delete this Task.", properties.UserDisplayName);
            }
            catch
            {
                errorMessage = "You are not allowed to delete a task.";
            }
            finally
            {
                properties.ErrorMessage = errorMessage;
            }
            properties.Cancel = true;
            properties.Status = SPEventReceiverStatus.CancelWithError;
        }
    }
}

Next, when your workflow starts, call a method similar to the following to register the custom event receiver.
My example includes calls to my custom trace feature, so you’ll have to eliminate them before you can use this code.

#region PreventWorkflowTaskDeletion
        ///
        /// Prevent workflow tasks from being deleted by adding an event receiver that will cancel any
        /// attempt to delete a task from the workflow task list.
        ///
        private void PreventWorkflowTaskDeletion()
        {
            string methodName = MethodBase.GetCurrentMethod().Name;
            TraceEnter(methodName);

            string message = string.Empty;

            // prevent multiple ItemDeleting event receivers from being attached to the task list by removing any that may already exist.
            // NOTE: has the added benefit of replacing existing event receiver if we made a code change and redeployed recently.
            SPEventReceiverDefinitionCollection evrs = workflowProperties.Workflow.TaskList.EventReceivers;
            List ersToDelete = new List();
            foreach (SPEventReceiverDefinition er in evrs)
            {
                if (er.Type == SPEventReceiverType.ItemDeleting)
                {
                    // add the GUID index of the Event Receiver to the list of ones we need to get rid of
                    ersToDelete.Add(er.Id);
                }
            }

            // have to wait until outside of the above loop to delete; otherwise, you get this error:
            // System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
            foreach (Guid i in ersToDelete)
            {
                message = string.Format("Removed ItemDeleting event reciever with GUID of {0}", i.ToString());
                TraceInfo(message);
                evrs[i].Delete();
                workflowProperties.Workflow.TaskList.Update();
            }

            // Example: "Microsoft.Office.Samples.ECM.Workflow.ReplicatorContactSelectorSample, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ec457ebe7d96977c";
            string assembly = Assembly.GetExecutingAssembly().FullName;
            message = string.Format("assembly = {0}", assembly);
            TraceInfo(message);

            // Example: "Microsoft.Office.Samples.ECM.Workflow.PreventWorkflowTaskDelete";
            string className = typeof(PreventWorkflowTaskDelete).FullName;
            message = string.Format("className = {0}", className);
            TraceInfo(message);

            // add the ItemDeleting event receiver to the current workflow task list
            try
            {
                workflowProperties.Workflow.TaskList.EventReceivers.Add(SPEventReceiverType.ItemDeleting, assembly, className);
                workflowProperties.Workflow.TaskList.Update();
                message = string.Format("Added ItemDeleting event");
            }
            catch (Exception ex)
            {
                message = string.Format("ERROR: Method {0} had an exception while attempting workflowProperties.Workflow.TaskList.EventReceivers.Add : {0}", ex.Message);
                TraceError(message);
                throw new SPException(message);
            }
            finally
            {
                TraceInfo(message);
            }

        }
        #endregion

In the above code, I was making frequent changes to the event receiver, thus the need to remove and re-add the event receiver each time.

Advertisements

2 thoughts on “Prevent Workflow Tasks From Being Deleted

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s