Remplacer les SharePoint créées à partir des définitions de liste dans les solutions de batterie de serveurs

Si vous avez utilisé des définitions de liste pour créer des listes dans votre solution de batterie de serveurs, découvrez comment les transformer en nouvelles solutions qui fournissent des fonctionnalités similaires à l’aide du modèle objet client (CSOM).

Important

Les solutions de batterie de serveurs ne peuvent pas être migrées vers SharePoint Online. En appliquant les techniques et le code décrits dans cet article, vous pouvez créer une nouvelle solution avec une fonctionnalité similaire offerte par votre solution de batterie de serveurs, laquelle peut ensuite être déployée sur SharePoint Online. Si vous utilisez une approche de transformation sur place, vous devrez peut-être déployer la nouvelle solution sur SharePoint Online. Si vous utilisez l’approche de migration de contenu ou de gestion de contenu, les outils tiers peuvent créer les listes pour vous. Pour plus d’informations, voir Approches de transformationpour déployer votre nouveau SharePoint.

Le code dans cet article requiert un code supplémentaire pour offrir une solution totalement fonctionnelle. Par exemple, cet article ne traite pas de l’authentification à Office 365, de la manière d’implémenter la gestion des exceptions, etc. Pour plus d’exemples de code, reportez-vous à la rubrique Pratiques et modèles de développement Office 365.

Notes

Le code dans cet article est fourni tel quel, sans garantie d’aucune sorte, expresse ou implicite, y compris mais sans s’y limiter, aucune garantie implicite d’adéquation à un usage particulier, à une qualité marchande ou une absence de contrefaçon.

Conseil

Utilisez les techniques décrites dans cet article pour mettre à jour quelques listes à la fois. En outre, lorsque vous recherchez des listes à mettre à jour, vous ne devez pas filtrer les listes par type de liste.

Pour remplacer les listes créées à partir de définitions de liste à l’aide du CSOM :

  1. Recherchez les listes qui ont été créées à l’aide d’un modèle de base spécifique.

  2. Créez la liste à l’aide de la définition de liste pré-standard.

  3. Configurez les paramètres de liste.

  4. Définissez les types de contenu sur la nouvelle liste en fonction des types de contenu qui ont été définies sur la liste d’origine.

  5. Ajouter ou supprimer des affichages (facultatif).

  6. Migrez le contenu de la liste d’origine vers la nouvelle liste.

Avant de commencer

Dans l’idéal, vous devez examiner vos solutions de batterie existantes, en savoir plus sur les techniques décrites dans cet article, puis planifier l’application de ces techniques à vos solutions de batterie existantes. Si vous ne connaissez pas les solutions de batterie de serveurs ou si vous n’avez pas de solution de batterie de serveurs existante à travailler, il peut vous être utile de :

  1. Examinez remplacer les listes créées à partir de modèles personnalisés pour comprendre rapidement comment les listes ont été créées de manière déclarative à l’aide de définitions de liste.

    Notes

    Dans Contoso.Intranet, dans le fichier elements.xml pour SP\ListTemplate\LTContosoLibrary, l’ID du modèle de liste personnalisé est 10003. Vous l’utiliserez pour identifier le modèle qui a été utilisé pour créer la liste. Examinez également les paramètres de configuration et les affichages définis dans votre liste.

  2. Découvrez les solutions de batterie de serveurs. Pour plus d’informations, voir Créer des solutions de batterie de serveurs dans SharePoint.

Rechercher les listes qui ont été créées à l’aide d’un modèle de base spécifique

Dans le code suivant, la méthode montre comment rechercher des listes qui ont été créées à l’aide d’un modèle de base spécifique. Cette méthode :

  1. Utilise clientContext pour obtenir toutes les listes dans le site web actuel à l’aide de Web.Lists. L’instruction Include est utilisée dans l’expression lambda pour renvoyer une collection de listes. Les listes renvoyées doivent toutes avoir des valeurs de propriété spécifiées pour BaseTemplate, BaseTypeet Title.

  2. Pour chaque liste de la collection de listes retournées, si le list.BaseTemplate est égal à 10003, ajoute la liste à une collection de listes à remplacer, appelée listsToReplace. N’oubliez pas que 10003 était l’identificateur du modèle de liste personnalisé que nous avons examiné dans l’exemple Contoso.Intranet.

     static void Main(string[] args)
     {
         using (var clientContext = new ClientContext("http://w15-sp/sites/ftclab"))
         {
             Web web = clientContext.Web;
             ListCollection listCollection = web.Lists;
             clientContext.Load(listCollection,
                                 l => l.Include(list => list.BaseTemplate,
                                                 list => list.BaseType,
                                                 list => list.Title));
             clientContext.ExecuteQuery();
             var listsToReplace = new List<List>();
             foreach (List list in listCollection)
             {
                 // 10003 is the custom list template ID of the list template you're replacing.
                 if (list.BaseTemplate == 10003)
                 {
                     listsToReplace.Add(list);
                 }
             }
             foreach (List list in listsToReplace)
             {
                 ReplaceList(clientContext, listCollection, list);
             }
         }
     }
    

    Important

    Dans le code précédent, vous devez d’abord itérer sur listCollection pour sélectionner les listes à modifier, puis appeler ReplaceList, qui commence à modifier les listes. Ce modèle est obligatoire car la modification du contenu d’une collection lors d’une itère sur la collection permet de faire une exception.

  3. Après avoir identifié une liste à remplacer, ReplaceList indique l’ordre des opérations à effectuer pour remplacer la liste.

     private static void ReplaceList(ClientContext clientContext, ListCollection listCollection, List listToBeReplaced)
     {
         var newList = CreateReplacementList(clientContext, listCollection, listToBeReplaced);
    
         SetListSettings(clientContext, listToBeReplaced, newList);
    
         SetContentTypes(clientContext, listToBeReplaced, newList);
    
         AddViews(clientContext, listToBeReplaced, newList);
    
         RemoveViews(clientContext, listToBeReplaced, newList);
    
         MigrateContent(clientContext, listToBeReplaced, newList);
     }
    

Créer une liste

Pour créer une liste, CreateReplacementList utilise ListCreationInformation.

Le titre de la nouvelle liste est définie sur le titre de la liste existante, avec le add-in ajouté à celui-ci. L’énumération ListTemplateType est utilisée pour définir le type de modèle de la liste sur une bibliothèque de documents. Si vous créez une liste basée sur un type de modèle différent, veillez à utiliser le type de modèle correct. Par exemple, si vous créez une liste de calendriers, utilisez ListTemplateType.Events au lieu de ListTemplateType.DocumentLibrary.

private static List CreateReplacementList(ClientContext clientContext, ListCollection lists,List listToBeReplaced)
{
    var creationInformation = new ListCreationInformation
    {
        Title = listToBeReplaced.Title + "add-in",
        TemplateType = (int) ListTemplateType.DocumentLibrary,
    };
    List newList = lists.Add(creationInformation);
    clientContext.ExecuteQuery();
    return newList;
}

Configurer les paramètres de liste

SetListSettings applique les paramètres de liste d’origine à la nouvelle liste en :

  1. Obtention de différents paramètres de liste à partir de la liste d’origine.

  2. Application du paramètre de liste de la liste d’origine à la nouvelle liste.

private static void SetListSettings(ClientContext clientContext, List listToBeReplaced, List newList)
{
    clientContext.Load(listToBeReplaced, 
                        l => l.EnableVersioning, 
                        l => l.EnableModeration, 
                        l => l.EnableMinorVersions,
                        l => l.DraftVersionVisibility );
    clientContext.ExecuteQuery();
    newList.EnableVersioning = listToBeReplaced.EnableVersioning;
    newList.EnableModeration = listToBeReplaced.EnableModeration;
    newList.EnableMinorVersions= listToBeReplaced.EnableMinorVersions;
    newList.DraftVersionVisibility = listToBeReplaced.DraftVersionVisibility;
    newList.Update();
    clientContext.ExecuteQuery();
}

Notes

En fonction de vos besoins, les paramètres de liste de vos listes d’origine peuvent être différents. Examinez vos paramètres de liste et modifiez SetListSettings pour vous assurer que vos paramètres de liste d’origine sont appliqués à vos nouvelles listes.

Définir des types de contenu sur la nouvelle liste

SetContentTypes définit les types de contenu sur la nouvelle liste en :

  1. Obtention d’informations sur le type de contenu à partir de la liste d’origine.

  2. Obtention des informations de type de contenu à partir de la nouvelle liste.

  3. Déterminer si la liste d’origine active les types de contenu. Si la liste d’origine n’active pas les types de contenu, SetContentTypes se quitte. Si la liste d’origine permettait les types de contenu, SetContentTypes active les types de contenu sur la nouvelle liste à l’aide de newList.ContentTypesEnabled = true.

  4. Pour chaque type de contenu de la liste d’origine, recherchez les types de contenu dans la nouvelle liste pour trouver un type de contenu correspondant basé sur le nom du type de contenu à l’aide de newList.ContentTypes.Any(ct => ct. Name == contentType.Name). Si le type de contenu ne figure pas dans la nouvelle liste, il est ajouté à la liste.

  5. Chargement de newList une deuxième fois, car AddExistingContentType a peut-être modifié les types de contenu.

  6. Pour chaque type de contenu dans newList, déterminez si le type de contenu correspond à un type de contenu dans la liste d’origine basée sur ContentType.Name à l’aide de listToBeReplaced.ContentTypes.Any(ct => ct. Name == contentType.Name). Si une correspondance est in trouvée, le type de contenu est ajouté à contentTypesToDelete pour être supprimé de la nouvelle liste.

  7. Suppression du type de contenu en appelant ContentType.DeleteObject.

Notes

Si vous utilisez une approche de transformation sur place et que vos types de contenu ont été déployés de manière déclarative à l’aide de Feature Framework, vous devez :

  1. Créez de nouveaux types de contenu.
  2. Définissez le type de contenu sur les éléments de liste lors de la migration du contenu de la liste d’origine vers la nouvelle liste dans MigrateContent.
private static void SetContentTypes(ClientContext clientContext, List listToBeReplaced, List newList)
{
    clientContext.Load(listToBeReplaced,
                        l => l.ContentTypesEnabled,
                        l => l.ContentTypes);
    clientContext.Load(newList,
                        l => l.ContentTypesEnabled,
                        l => l.ContentTypes);
    clientContext.ExecuteQuery();

    // If the original list doesn't use content types, do not proceed any further.
    if (!listToBeReplaced.ContentTypesEnabled) return;

    newList.ContentTypesEnabled = true;
    newList.Update();
    clientContext.ExecuteQuery();
    foreach (var contentType in listToBeReplaced.ContentTypes)
    {
        if (!newList.ContentTypes.Any(ct => ct.Name == contentType.Name))
        {
            // Current content type needs to be added to the new list. Note that the content type is added to the list, not the site.           
            newList.ContentTypes.AddExistingContentType(contentType.Parent);
            newList.Update();
            clientContext.ExecuteQuery();
        }
    }
    // Reload the content types on newList because they might have changed when AddExistingContentType was called. 
    clientContext.Load(newList, l => l.ContentTypes);
    clientContext.ExecuteQuery();
    // Remove any content types that are not needed.
    var contentTypesToDelete = new List<ContentType>();
    foreach (var contentType in newList.ContentTypes)
    {
        if (!listToBeReplaced.ContentTypes.Any(ct => ct.Name == contentType.Name))
        {
            // Current content type needs to be removed from new list.
            contentTypesToDelete.Add(contentType);
        }
    }
    foreach (var contentType in contentTypesToDelete)
    {
        contentType.DeleteObject();
    }
    newList.Update();
    clientContext.ExecuteQuery();
}

Notes

À ce stade, la nouvelle liste peut accepter le contenu de la liste d’origine. Vous pouvez également ajouter et supprimer des affichages.

Ajouter ou supprimer des affichages (facultatif)

Les utilisateurs peuvent ajouter ou supprimer des affichages définis sur une liste pour répondre aux besoins de l’entreprise. Pour cette raison, vous devrez peut-être ajouter ou supprimer des affichages sur la nouvelle liste.

Ajouter des affichages à la nouvelle liste

AddViews ajoute des vues de la liste d’origine à la nouvelle liste en :

  1. Utilisation de List.Views pour obtenir tous les affichages de la liste d’origine.

  2. Utilisation de l’expression lambda pour charger différentes propriétés d’affichage sur la collection views.

  3. Pour chaque affichage de la liste d’origine, créez un affichage à l’aide de ViewCreationInformation.

    Diverses propriétés sont définies sur la nouvelle vue en fonction des propriétés d’affichage de l’affichage d’origine. La méthode d’aide GetViewType est appelée pour déterminer le ViewType de l’affichage. La nouvelle vue est ensuite ajoutée à la liste des vues appelée viewsToCreate.

  4. Ajout des vues à la collection List.Views à l’aide de la méthode Add sur la collection Views de la liste.

     private static void AddViews(ClientContext clientContext, List listToBeReplaced, List newList)
     {
         ViewCollection views = listToBeReplaced.Views;
         clientContext.Load(views,
                             v => v.Include(view => view.Paged,
                                 view => view.PersonalView,
                                 view => view.ViewQuery,
                                 view => view.Title,
                                 view => view.RowLimit,
                                 view => view.DefaultView,
                                 view => view.ViewFields,
                                 view => view.ViewType));
         clientContext.ExecuteQuery();
    
         // Build a list of views which exist on the original list only.
         var viewsToCreate = new List<ViewCreationInformation>();
         foreach (View view in listToBeReplaced.Views)
         {
         var createInfo = new ViewCreationInformation
         {
             Paged = view.Paged,
             PersonalView = view.PersonalView,
             Query = view.ViewQuery,
             Title = view.Title,
             RowLimit = view.RowLimit,
             SetAsDefaultView = view.DefaultView,
             ViewFields = view.ViewFields.ToArray(),
             ViewTypeKind = GetViewType(view.ViewType),
         };
         viewsToCreate.Add(createInfo);
         }
    
         foreach (ViewCreationInformation newView in viewsToCreate)
         {
             newList.Views.Add(newView);
         }
         newList.Update();
     }
    
     private static ViewType GetViewType(string viewType)
     {
         switch (viewType)
         {
             case "HTML":
                 return ViewType.Html;
             case "GRID":
                 return ViewType.Grid;
             case "CALENDAR":
                 return ViewType.Calendar;
             case "RECURRENCE":
                 return ViewType.Recurrence;
             case "CHART":
                 return ViewType.Chart;
             case "GANTT":
                 return ViewType.Gantt;
             default:
                 return ViewType.None;
         }
     }
    

Supprimer des affichages de la nouvelle liste

Dans le code suivant, RemoveViews supprime les affichages de la nouvelle liste en :

  1. Obtention des affichages de liste sur la nouvelle liste à l’aide de la propriété List.Views.

  2. Pour chaque affichage de la nouvelle liste, déterminez si cet affichage n’existe pas dans la liste d’origine en correspondant au titre de l’affichage à l’aide de !listToBeReplaced.Views.Any(v => v.Title == affichage. Titre. Si un affichage de la nouvelle liste n’a pas d’affichage correspondant dans la liste d’origine, ajoutez l’affichage à viewsToRemove.

  3. Suppression de tous les affichages dans viewsToRemove à l’aide de View.DeleteObject.

     private static void RemoveViews(ClientContext clientContext, List listToBeReplaced, List newList)
     {
         // Get the list of views on the new list.
         clientContext.Load(newList, l => l.Views);
         clientContext.ExecuteQuery();
    
         var viewsToRemove = new List<View>();
         foreach (View view in newList.Views)
         {
             if (!listToBeReplaced.Views.Any(v => v.Title == view.Title))
             {
                 // If there is no matching view in the source list, add the view to the list of views to be deleted.
                 viewsToRemove.Add(view);
             }
         }
         foreach (View view in viewsToRemove)
         {
             view.DeleteObject();
         }
         newList.Update();
         clientContext.ExecuteQuery();
     }
    

Migrer le contenu de la liste d’origine vers la nouvelle liste

MigrateContent migre le contenu de la liste d’origine vers la nouvelle liste en :

  1. Récupération de la destination vers qui copier les fichiers ou le dossier racine de la nouvelle liste, à l’aide de List.RootFolder. L’URL relative de serveur du dossier de liste de destination est récupérée à l’aide de Folder.ServerRelativeUrl.

  2. Récupération de la source des fichiers, ou du dossier racine de la liste d’origine, à l’aide de List.RootFolder. L’URL relative de serveur du dossier de liste et tous les fichiers du dossier racine de la source sont chargés à l’aide de l’objet clientContext.

  3. Pour chaque fichier dans la source, la création de newUrl, qui stocke la nouvelle URL du fichier. newUrl est créé en remplaçant le dossier racine source par le dossier racine de la destination.

  4. Utilisation de File.CopyTo pour copier le fichier vers l’URL du dossier racine de destination. Vous pouvez également choisir d’utiliser la méthode File.MoveTo pour déplacer le fichier vers l’URL de destination.

Notes

Le code suivant renvoie tous les éléments de liste. Dans votre environnement de production, envisagez d’optimiser le code suivant en implémentant une boucle et en utilisant plusieurs itérations pour migrer de petites quantités d’éléments de liste.

private static void MigrateContent(ClientContext clientContext, List listToBeReplaced, List newList)
{
    ListItemCollection items = listToBeReplaced.GetItems(CamlQuery.CreateAllItemsQuery());
    Folder destination = newList.RootFolder;
    Folder source = listToBeReplaced.RootFolder;
    clientContext.Load(destination,
                        d => d.ServerRelativeUrl);
    clientContext.Load(source,
                        s => s.Files,
                        s => s.ServerRelativeUrl);
    clientContext.Load(items,
                        i => i.IncludeWithDefaultProperties(item => item.File));
    clientContext.ExecuteQuery();


    foreach (File file in source.Files)
    {
        string newUrl = file.ServerRelativeUrl.Replace(source.ServerRelativeUrl, destination.ServerRelativeUrl);
          file.CopyTo(newUrl, true);
          //file.MoveTo(newUrl, MoveOperations.Overwrite);
    }
    clientContext.ExecuteQuery();
}

Notes

Le code précédent montre comment migrer des fichiers stockés dans le dossier racine d’une liste. Si votre liste contient des sous-foldeurs, vous devez ajouter du code supplémentaire pour migrer les sous-foldeurs et leur contenu. Si votre liste utilise des flux de travail, du code supplémentaire est requis pour associer le flux de travail à la nouvelle liste.

Voir aussi