Try our conversational search powered by Generative AI!

Delete page/block properties in bulk that are missing from code.

ZZ
ZZ
Vote:
 

Hi,

Is there any way to delete page/block properties from CMS that doesn't exsist in the code anymore ?

I know you can delete it one by one from admin menu, but is there any plugin or otherway to delete all the properties that doesn't exsist in the code

#305626
Jul 24, 2023 10:14
Vote:
 

You can implemente functionality for remove unused properties.
Hope this blog will help...
https://world.optimizely.com/blogs/sanjay-katiyar/dates/2022/10/delete-unused-properties-and-content-types-in-cms-12/

#305627
Jul 24, 2023 11:16
Vote:
 

Since other changes in the types are migrations, and MigrationSteps run on the app starting, this is what I do. This is for CMS 11 and below so some things might need change.

public class MigrationsYYYYMMDD : MigrationStep {
  public override void AddChanges() {
    DeleteProperties(typeof(WhateverPage), "Someproperty");
  }
  private void DeleteProperties(Type contentType, params string[] propertyNames) {
    var contentTypeModel = ServiceLocator.Current.GetInstance<IContentTypeRepository>().Load(contentType);
    var propertyDefinitions = contentTypeModel.PropertyDefinitions.Where(x => propertyNames.Contains(x.Name));
    IPropertyDefinitionRepository propertyDefinitionRepository = null;
    foreach (var propertyDefinition in propertyDefinitions) {
      propertyDefinitionRepository = propertyDefinitionRepository ?? ServiceLocator.Current.GetInstance<IPropertyDefinitionRepository>();
      try {
        propertyDefinitionRepository.Delete(propertyDefinition.CreateWritableClone());
      }
      // ReSharper disable once EmptyGeneralCatchClause
      // We don't care if it doesn't work, but we don't want to make the site go down, so just ignore errors here.
      catch (Exception) {
      }
    }
  }
}

Since it's a bit hard to keep track of what you deleted I have a report that runs the following code and then I copy/paste from this report into a code file and verify that all looks good. I don't think it's a good idea to automate the deletion completely since that might remove data you want to keep and there is no going back except restoring backups, and that has it's own problems. (This is for CMS 11, so might need modifications.)

      var buffer = new StringBuilder();
      var contentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
      buffer.AppendLine(@"<pre>
public class Migrations" + DateTime.UtcNow.ToString("yyyyMMddhhmm") + @" : MigrationStep {
  public override void AddChanges() {");
      foreach (var contentType in contentTypeRepository.List()) {
        if(contentType.ModelType == null) continue;
        foreach (var propertyDefinition in contentType.PropertyDefinitions) {
          // ExistsOnModel lies some times for unkonwn reasons... if(propertyDefinition.ExistsOnModel) continue;
          if(contentType.ModelType.GetProperty(propertyDefinition.Name) != null) continue;
          buffer.AppendLine($"    DeleteProperties(typeof({contentType.Name}), \"{propertyDefinition.Name}\");");
        }
      }
      buffer.AppendLine(@"  }
  private void DeleteProperties(Type contentType, params string[] propertyNames) {
    var contentTypeModel = ServiceLocator.Current.GetInstance&lt;IContentTypeRepository&gt;().Load(contentType);
    var propertyDefinitions = contentTypeModel.PropertyDefinitions.Where(x =&gt; propertyNames.Contains(x.Name));
    IPropertyDefinitionRepository propertyDefinitionRepository = null;
    foreach (var propertyDefinition in propertyDefinitions) {
      propertyDefinitionRepository = propertyDefinitionRepository ?? ServiceLocator.Current.GetInstance&lt;IPropertyDefinitionRepository&gt;();
      try {
        propertyDefinitionRepository.Delete(propertyDefinition.CreateWritableClone());
      }
      // ReSharper disable once EmptyGeneralCatchClause
      // We don't care if it doesn't work, but we don't want to make the site go down, so just ignore errors here.
      catch (Exception) {
      }
    }
  }

}</pre>");
#305629
Jul 24, 2023 13:38
Vote:
 

Hi ZZ

Since the content type manager can do that, you can script it, too. For instance on a protected page or as a scheduled job.

It could do something like this:

  1. Find all content types, using IContentTypeRepository.List.
    1. Filter out system pages, like SysRoot and SysRecycleBin, because they never have properties in code.
  2. For each of those content types, look up the property definitions, and for each of those see whether or not they have ExistsOnModel == true.
  3. Delete those property definitions that have ExistsOnModel == false, using IPropertyDefinitionRepository.Delete.

Test this well with a backup before doing this in production (or even in test). Just in case it deletes too much.

#305632
Jul 24, 2023 16:14
ZZ
Vote:
 

Thanks for the input. I also need to find out the block / page name out of the content id, so I can show in the message which blocks / pages properties were part of that are deleted

                        var contentTypeName = _contentRepository.Get<BlockData>(new ContentReference(property.ContentTypeID));

This code line is throwing an error that content not found 

#305682
Jul 25, 2023 12:25
ZZ
Vote:
 

I can see that the function also deletes some properties from EpiServer.Forms. How to only delete pages / blocks that are developed by us and not properties that are build into EpIServer

#305685
Jul 25, 2023 13:38
ZZ
Vote:
 

After executing the fucntion it also deletes the block properties which I never created

Name='Forms_ExternalSystemsFieldMappings', id='7889', ContentType='1298'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7882', ContentType='1297'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7878', ContentType='1290'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7887', ContentType='1281'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7888', ContentType='1282'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7886', ContentType='1280'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7880', ContentType='1293'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7884', ContentType='1299'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7881', ContentType='1295'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7876', ContentType='1287'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7877', ContentType='1289'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7879', ContentType='1292'), Result(TypeName='Property Field Mapping Collection', Name='Forms_ExternalSystemsFieldMappings', id='7885', ContentType='1300'), Result(TypeName='Message Template',

#305721
Jul 26, 2023 8:32
ZZ
Vote:
 

I only want to delete properties of those blocks that we creates not something that is part of Optimizely plugins etc.

#305722
Jul 26, 2023 8:38
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.