Scott Reed
Nov 9, 2020
  1969
(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
Opti ID overview

Opti ID allows you to log in once and switch between Optimizely products using Okta, Entra ID, or a local account. You can also manage all your use...

K Khan | Jul 26, 2024

Getting Started with Optimizely SaaS using Next.js Starter App - Extend a component - Part 3

This is the final part of our Optimizely SaaS CMS proof-of-concept (POC) blog series. In this post, we'll dive into extending a component within th...

Raghavendra Murthy | Jul 23, 2024 | Syndicated blog

Optimizely Graph – Faceting with Geta Categories

Overview As Optimizely Graph (and Content Cloud SaaS) makes its global debut, it is known that there are going to be some bugs and quirks. One of t...

Eric Markson | Jul 22, 2024 | Syndicated blog

Integration Bynder (DAM) with Optimizely

Bynder is a comprehensive digital asset management (DAM) platform that enables businesses to efficiently manage, store, organize, and share their...

Sanjay Kumar | Jul 22, 2024

Frontend Hosting for SaaS CMS Solutions

Introduction Now that CMS SaaS Core has gone into general availability, it is a good time to start discussing where to host the head. SaaS Core is...

Minesh Shah (Netcel) | Jul 20, 2024

Optimizely London Dev Meetup 11th July 2024

On 11th July 2024 in London Niteco and Netcel along with Optimizely ran the London Developer meetup. There was an great agenda of talks that we put...

Scott Reed | Jul 19, 2024