Scott Reed
Nov 9, 2020
  3653
(2 votes)

Handling Delete Content Events Within the Waste Basket / Trash

When working with episerver content events expsed to you via the IContentEvents service that involve deleting content we have a couple of events

  • DeletingContent - Which fires when attempting to delete content and allows you to return a boolean to stop it
  • DeletedContent - Which fires after the item has been deleted.

However it's important to be aware when these events fire...

Both of these events actually fire when deleting from trash directly or when clicking the "Empty Trash" button. If you were these to fire when the item is moved to trash / waste basket you'd be wrong and you actually need to handle the MovedContent / MovingContent events.

Now when it comes to working with these two deletion events it's important to know that there's an odd kink in how these work depending on if you've selected Delete on an item in trash or you've clicked the "Empty Trash" button.

The key difference is

  1. When handling the event from a direct delete on a specific item in the trash / waste basket, the passed item to the event handler is the ContentLink of the item
  2. When handing the event from the "Empty Trash" button, the passed item to the event handler in the ContentLink of the WasteBasket. It's also worth noting that getting the children of the waste basket DID NOT work and I had to use descendants.

So as a code example in a recent project I had to hook in to this event to delete an item from a custom database table sorting some related information and this lead to me implementing the following (excuse the use of DataFactory / No Dependency Inject it's due to the project it's used on).

// <summary>
    /// Handles content events from Episerver
    /// </summary>
    /// <seealso cref=IInitializableModule" />
    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class ContentEventsInitialization : IInitializableModule
    {
        /// <summary>
        /// Initializes this instance.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <remarks>
        /// Gets called as part of the EPiServer Framework initialization sequence. Note that it will be called
        /// only once per AppDomain, unless the method throws an exception. If an exception is thrown, the initialization
        /// method will be called repeadetly for each request reaching the site until the method succeeds.
        /// </remarks>
        public void Initialize(InitializationEngine context)
        {
            var events = ServiceLocator.Current.GetInstance<IContentEvents>();
            events.DeletingContent += DeletingContent;
        }

        /// <summary>
        /// Preloads the specified parameters.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        public void Preload(string[] parameters)
        {
        }

        /// <summary>
        /// Resets the module into an uninitialized state.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <remarks>
        /// <para>
        /// This method is usually not called when running under a web application since the web app may be shut down very
        /// abruptly, but your module should still implement it properly since it will make integration and unit testing
        /// much simpler.
        /// </para>
        /// <para>
        /// Any work done by <see cref="M:EPiServer.Framework.IInitializableModule.Initialize(EPiServer.Framework.Initialization.InitializationEngine)" /> as well as any code executing on <see cref="E:EPiServer.Framework.Initialization.InitializationEngine.InitComplete" /> should be reversed.
        /// </para>
        /// </remarks>
        public void Uninitialize(InitializationEngine context)
        {
        }

        /// <summary>
        /// Deletings the content.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="ContentEventArgs"/> instance containing the event data.</param>
        private void DeletingContent(object sender, ContentEventArgs e)
        {
            RemoveAlertsFromDatabase(e);
        }

        /// <summary>
        /// Handles removing of alerts from database when they are deleted.
        /// </summary>
        /// <param name="e">The <see cref="ContentEventArgs"/> instance containing the event data.</param>
        private void RemoveAlertsFromDatabase(ContentEventArgs e)
        {
            var alertsManager = new AlertsManager();

            if (e.ContentLink.ID == ContentReference.WasteBasket.ID)
            {
                var wasteBasketReferences = DataFactory.Instance.GetDescendents(e.ContentLink);

                foreach (var wasteBasketReference in wasteBasketReferences)
                {
                    var item = DataFactory.Instance.Get<IContent>(wasteBasketReference);

                    if (item is AlertItem)
                    {
                        alertsManager.RemoveAlerts(wasteBasketReference.ID);
                    }
                }
            }

            if (e.Content is AlertItem)
            {
                alertsManager.RemoveAlerts(e.ContentLink.ID);
            }
        }
    }

Hopefully this helps anyone with working with delete events when in the trash

Nov 09, 2020

Comments

Please login to comment.
Latest blogs
Opal: Beyond the Obvious

A couple of less-obvious ways I'm using Optimizely's Opal to automate real work across Salesforce, GitHub, and Teams.

Daniel Isaacs | Jun 18, 2026 |

EOL Announcement for Preview3 CMS REST API

Action Required: Migrate Preview3 API Integrations to CMS REST API v1 Before August 1, 2026 If your SaaS CMS applications are currently using the...

Kathy Copeland | Jun 18, 2026

Environmental DXP badges

I recently released my first Optimizely add-on in a while, that was based on some client feedback on the Optimizely DXP – they wanted to be able to...

Matt Pallatt | Jun 18, 2026

CI/CD deployment failure in Optimizely DXP Passportal. .NET 10 and GitHub Runner Compatibility

.NET 10 and GitHub Runner Compatibility With the release of .NET 10, the windows-latest and ubuntu-latest GitHub Actions runners may use the latest...

owaiskhan | Jun 16, 2026