Wenn Projektseitig per Zip-Datei Grids ausgeliefert werden, bei denen Spalten-Steuerelemente durch andere Spalten-Steuerelemente ersetzt werden, gehen in diesem Moment dazu gespeicherte Ansichten “kaputt” in dem Sinne, dass die ursprüngliche Spalte nicht mehr angezeigt wird und die neue Spalte nur in der Spaltenauswahl vorhanden ist, aber nicht standardmäßig sichtbar ist.

Um dieses Problem zum umgehen, kann eine Config-Migration geschrieben werden, die in den gespeicherten Ansichten die alten IDs der Spalten durch die neuen ersetzt. Um die Migration zu vereinfachen, gibt es eine neue Hilfsfunktion: ClientLayoutSerializer.UpdateTechnicalNamesOfGridColumns()

Beispielhafte Implementierung:

 /// <summary>
 /// Migration to update control internal names within saved layouts
 /// </summary>
 [MigrationScript("8.0", 1)]
 public class Migration_01_UpdateSavedLayouts : ConfigurationMigrationBase
 {
     /// <summary>
     /// ctor
     /// </summary>
     public Migration_01_UpdateSavedLayouts() : base(EnumConfigurationType.GridConfiguration) { }

     /// <inheritdoc/>
     public override bool ExecuteTheScriptForConfiguration(MigrationExecutor executionContext)
     {
         // should be only executed when importing zips
         return false;
     }

    /// <inheritdoc/>
    public override bool ExecuteTheScriptAfterStart(MigrationExecutor executionContext)
    {
        if (ConfigurationManager.AppSettings.GetBool("BA:Configuration.DisableImplicitImport", false))
            return false;

        // it is wanted here to call *another* base method
        return base.ExecuteTheScriptForConfiguration(executionContext);
    }

     /// <inheritdoc/>
     protected override void MigrateConfiguration(EnumConfigurationType type, Guid id, ref string xml)
     {
         GridViewConfiguration existingGridViewConfig = Api.Config.TryGrid(id);
         if (existingGridViewConfig == null || existingGridViewConfig.ProtectAgainstUpdate)
             return;

         IEnumerable<KeyValuePair<string, string>> mappings = GetMappingsForConfiguration(id);
         if (mappings == null)
             return;

         IReadOnlyList<GridViewLayoutConfiguration> layouts = Api.Config.GetGridLayouts(id);
         foreach (GridViewLayoutConfiguration layout in layouts)
         {
             string layoutDataNew = ClientLayoutSerializer.UpdateTechnicalNamesOfGridColumns(layout.LayoutData, mappings);
             layout.LayoutData = layoutDataNew;
             layout.Save();
         }
     }

     private IEnumerable<KeyValuePair<string, string>> GetMappingsForConfiguration(Guid correspondingConfiguration)
     {
         List<KeyValuePair<string, string>> mappings = new List<KeyValuePair<string, string>>();

         if (correspondingConfiguration == "12aeb0e6-f070-45ba-bfb2-96778fe812b5".ToGuid()) // Contacts
         {
             // old id, new id
             mappings.Add(new KeyValuePair<string, string>("CalculatedColumn75afd3dab52d4405a73760991ccb18d4", "parentIndustry559460599"));
         } 
         // else if ... etc

         if (mappings.Any())
             return mappings;
         else
             return null;
     }
 }