World is now on Opti ID! Learn more

sanjay.kumar
Oct 8, 2022
  70
(0 votes)

Delete unused properties and content types in CMS 12

The purpose of this blog is to delete unused properties, content references, and content types programmatically and keep clean content.

Problem: I have created a block type (e.g. TeaserBlock) and using this block created multiple contents and used it in different places, but after some time the requirement was changed and I removed this block type completely from the code. So for cleanup, we need to remove this block type from the Admin --> Content Types area in CMS because it no longer exists. But when I tried to delete it, we got content reference warnings because we already created content using a specific block type and added those references at many places (e.g. Main Content Area of other pages).

Then the question comes to mind how to delete it? So I tried the following solution and fixed it.

Solution

We have two options two remove the missing content type and its references:

  1. Remove all references from each content type and then delete it from the Admin -> Content Types area. - This is a time-consuming activity because you need to visit and delete each content type (moving and emptying the Trash folder).
  2. Write the code and clean up it programmatically.

I am using the second (2) option to achieve this.

Where do you write the code? I will suggest in the Initialization Module or create a Schedule Job to delete the unused properties and content types. It’s totally up to you  :)

Delete the missing properties which are no longer exist in the code for Content Type (PageType/BlockType): (e.g. TeaserBlock -> Sub Title)

 private void DeleteUnUsedProperties()
 {
            var pageTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository<PageType>>();
            var propertyDefinitionRepository = ServiceLocator.Current.GetInstance<IPropertyDefinitionRepository>();
            foreach (var type in pageTypeRepository.List())
            {
                foreach (var property in type.PropertyDefinitions)
                {
                    if (property != null && !property.ExistsOnModel)
                    {
                        propertyDefinitionRepository.Delete(property);
                    }
                }

               this.DeleteContentType(type);
            }

            var blockTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository<BlockType>>();
            foreach (var type in blockTypeRepository.List())
            {
                foreach (var property in type.PropertyDefinitions)
                {
                    if (property != null && !property.ExistsOnModel)
                    {                     
                        propertyDefinitionRepository.Delete(property);
                    }
                }

                this.DeleteContentType(type);
            }
        }

Delete the content references and missing content type (e.g. TeaserBlock)

  private void DeleteContentType(ContentType contentType)
  {
            if (contentType.ModelType != null)
            {
                return;
            }

            if (contentType.Saved != null &&
                contentType.Created.HasValue &&
                contentType.Created.Value.Year > 2021 &&
                contentType.IsAvailable)
            {
                // Find and deletes the content based on type.
                var contentModelUsage = ServiceLocator.Current.GetInstance<IContentModelUsage>();
                var contentUsages = contentModelUsage.ListContentOfContentType(contentType);
                var contentReferences = contentUsages
                    .Select(x => x.ContentLink.ToReferenceWithoutVersion())
                    .Distinct();

                var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
                foreach (var contentItem in contentReferences)
                {
                    contentRepository.Delete(contentItem, true, EPiServer.Security.AccessLevel.NoAccess);
                }

                // Delete type of content.
                var contentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
                if (contentType.ID > 4)
                {
                    contentTypeRepository.Delete(contentType.ID);
                }
            }
  }

Note: CotentType.ID > 4 means this will exclude the system/predefined page types e.g. Root Page.

Please leave your feedback in the comment box.

Thanks for your visit!

Oct 08, 2022

Comments

Please login to comment.
Latest blogs
Make Global Assets Site- and Language-Aware at Indexing Time

I had a support case the other day with a question around search on global assets on a multisite. This is the result of that investigation. This co...

dada | Jun 26, 2025

The remote server returned an error: (400) Bad Request – when configuring Azure Storage for an older Optimizely CMS site

How to fix a strange issue that occurred when I moved editor-uploaded files for some old Optimizely CMS 11 solutions to Azure Storage.

Tomas Hensrud Gulla | Jun 26, 2025 |

Enable Opal AI for your Optimizely products

Learn how to enable Opal AI, and meet your infinite workforce.

Tomas Hensrud Gulla | Jun 25, 2025 |

Deploying to Optimizely Frontend Hosting: A Practical Guide

Optimizely Frontend Hosting is a cloud-based solution for deploying headless frontend applications - currently supporting only Next.js projects. It...

Szymon Uryga | Jun 25, 2025

World on Opti ID

We're excited to announce that world.optimizely.com is now integrated with Opti ID! What does this mean for you? New Users:  You can now log in wit...

Patrick Lam | Jun 22, 2025

Avoid Scandinavian Letters in File Names in Optimizely CMS

Discover how Scandinavian letters in file names can break media in Optimizely CMS—and learn a simple code fix to automatically sanitize uploads for...

Henning Sjørbotten | Jun 19, 2025 |