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:
- 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).
- 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!
Comments