Partager via


Remplacer les listes SharePoint créées à partir de 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).

Importante

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 swing ou migration de contenu, les outils tiers peuvent créer les listes pour vous. Pour plus d’informations, consultez Approches de transformation pour déployer votre nouveau complément 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.

Remarque

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 seulement 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 de CSOM :

  1. Recherchez les listes 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ête à l’emploi.

  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éfinis sur la liste d’origine.

  5. Ajouter ou supprimer des vues (facultatif).

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

Avant de commencer

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

  1. Consultez Remplacement des 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.

    Remarque

    Dans Contoso.Intranet, dans le fichier elements.xml pour SP\ListTemplate\LTContosoLibrary, l’ID du modèle de liste personnalisé est 10003. Vous allez l’utiliser pour identifier le modèle qui a été utilisé pour créer la liste. Passez également en revue les paramètres de configuration et les vues 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 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 le ClientContext pour obtenir toutes les listes du 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 retournées doivent toutes avoir des valeurs de propriété spécifiées pour BaseTemplate, BaseType et Title.

  2. Pour chaque liste de la collection de listes retournées, si 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);
             }
         }
     }
    

    Importante

    Dans le code précédent, vous effectuez d’abord une itération sur listCollection pour sélectionner les listes à modifier, puis appelez ReplaceList, qui commence à modifier les listes. Ce modèle est obligatoire, car la modification du contenu d’une collection lors de l’itération sur la collection lève une exception.

  3. Après avoir identifié une liste à remplacer, ReplaceList affiche 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éfini sur le titre de la liste existante, avec le complément qui y est ajouté. 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 approprié. 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();
}

Remarque

En fonction de vos besoins, les paramètres de liste de vos listes d’origine peuvent être différents. Passez en revue 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 dans la nouvelle liste

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

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

  2. Obtention d’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 ferme. Si la liste d’origine a activé 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 dans la liste d’origine, recherchez les types de contenu de 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. Nom == 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 peut avoir modifié les types de contenu.

  6. Pour chaque type de contenu dans newList, déterminer si le type de contenu correspond à un type de contenu dans la liste d’origine en fonction de ContentType.Name à l’aide de listToBeReplaced.ContentTypes.Any(ct => ct. Nom == contentType.Name). Si aucune correspondance n’est 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.

Remarque

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 des 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();
}

Remarque

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

Ajouter ou supprimer des vues (facultatif)

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

Ajouter des vues à la nouvelle liste

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

  1. Utilisation de List.Views pour obtenir toutes les vues 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 vue de la liste d’origine, créez une vue à l’aide de ViewCreationInformation.

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

  4. Ajout des vues à la collection List.Views à l’aide de la méthode Add de 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 les vues de la nouvelle liste

Dans le code suivant, RemoveViews supprime les vues 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éterminer si cette vue n’existe pas dans la liste d’origine en faisant correspondre le titre de l’affichage à l’aide de !listToBeReplaced.Views.Any(v = v.Title> == view). Titre. Si une vue de la nouvelle liste n’a pas d’affichage correspondant dans la liste d’origine, ajoutez la vue à viewsToRemove.

  3. Suppression de toutes les vues 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 procédant comme suit :

  1. Récupération de la destination vers laquelle copier les fichiers, ou du dossier racine de la nouvelle liste, à l’aide de List.RootFolder. L’URL relative du 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 du 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 de la source, créez 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 dans 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.

Remarque

Le code suivant retourne 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();
}

Remarque

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

Voir aussi