Don't miss out Virtual Happy Hour this Friday (April 26).

Try our conversational search powered by Generative AI!

Scott Reed
Nov 9, 2020
  1817
(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
Solving the mystery of high memory usage

Sometimes, my work is easy, the problem could be resolved with one look (when I’m lucky enough to look at where it needs to be looked, just like th...

Quan Mai | Apr 22, 2024 | Syndicated blog

Search & Navigation reporting improvements

From version 16.1.0 there are some updates on the statistics pages: Add pagination to search phrase list Allows choosing a custom date range to get...

Phong | Apr 22, 2024

Optimizely and the never-ending story of the missing globe!

I've worked with Optimizely CMS for 14 years, and there are two things I'm obsessed with: Link validation and the globe that keeps disappearing on...

Tomas Hensrud Gulla | Apr 18, 2024 | Syndicated blog

Visitor Groups Usage Report For Optimizely CMS 12

This add-on offers detailed information on how visitor groups are used and how effective they are within Optimizely CMS. Editors can monitor and...

Adnan Zameer | Apr 18, 2024 | Syndicated blog