Freigeben über


Ersetzen von SharePoint-Listen, die aus Listendefinitionen in Farmlösungen erstellt wurden

Wenn Sie Listendefinitionen zum Erstellen von Listen in Ihrer Farmlösung verwendet haben, erfahren Sie, wie Sie diese mithilfe des Clientobjektmodells (CSOM) in neue Lösungen transformieren, die ähnliche Funktionen bereitstellen.

Wichtig

Farm-Lösungen können nicht zu SharePoint Online migriert werden. Durch Anwenden der Techniken und des Codes, die in diesem Artikel beschrieben sind, können Sie eine neue Lösung mit ähnlichen Funktionen wie die Ihrer Farm-Lösungen erstellen, die dann auf SharePoint Online bereitgestellt werden kann. Wenn Sie einen direkten Transformationsansatz verwenden, müssen Sie die neue Lösung möglicherweise in SharePoint Online bereitstellen. Wenn Sie den Swing- oder Inhaltsmigrationsansatz verwenden, können die Drittanbietertools die Listen für Sie erstellen. Weitere Informationen finden Sie unter Transformationsansätze zum Bereitstellen Ihres neuen SharePoint-Add-Ins.

Der Code in diesem Artikel erfordert zusätzlichen Code für die Bereitstellung einer vollständig funktionierenden Lösung. Beispielsweise wird in diesem Artikel nicht erläutert, wie Sie sich bei Office 365 authentifizieren, wie die erforderliche Ausnahmenbehandlung implementiert wird und so weiter. Weitere Codebeispiele, finden Sie unter Office 365 Developer Patterns and Practices Project.

Hinweis

Der Code in diesem Artikel wird wie besehen und ohne jegliche Garantie zur Verfügung gestellt, gleich ob ausdrücklich oder konkludent, einschließlich jedweder stillschweigenden Gewährleistung der Eignung für einen bestimmten Zweck, Marktgängigkeit oder Nichtverletzung von Rechten.

Tipp

Verwenden Sie die in diesem Artikel beschriebenen Techniken, um nur wenige Listen gleichzeitig zu aktualisieren. Außerdem sollten Sie beim Suchen nach zu aktualisierenden Listen die Listen nicht nach Listentyp filtern.

So ersetzen Sie Listen, die mithilfe von CSOM aus Listendefinitionen erstellt wurden:

  1. Suchen sie nach Listen, die mit einer bestimmten Basisvorlage erstellt wurden.

  2. Erstellen Sie die neue Liste mithilfe der vordefinierten Listendefinition.

  3. Konfigurieren Sie Listeneinstellungen.

  4. Legen Sie Inhaltstypen für die neue Liste basierend auf den Inhaltstypen fest, die in der ursprünglichen Liste festgelegt wurden.

  5. Hinzufügen oder Entfernen von Ansichten (optional).

  6. Migrieren Sie Inhalte aus der ursprünglichen Liste in die neue Liste.

Bevor Sie beginnen

Im Idealfall sollten Sie Ihre vorhandenen Farmlösungen überprüfen, sich über die in diesem Artikel beschriebenen Techniken informieren und dann planen, wie Sie diese Techniken auf Ihre vorhandenen Farmlösungen anwenden. Wenn Sie mit Farmlösungen nicht vertraut sind oder nicht über eine vorhandene Farmlösung verfügen, mit der Sie arbeiten können, kann dies für Sie hilfreich sein:

  1. Lesen Sie Ersetzen von Listen, die aus benutzerdefinierten Vorlagen erstellt wurden , um schnell zu verstehen, wie Listen mithilfe von Listendefinitionen deklarativ erstellt wurden.

    Hinweis

    In Contoso.Intranet ist in der elements.xml-Datei für SP\ListTemplate\LTContosoLibrary die ID für die benutzerdefinierte Listenvorlage 10003. Sie verwenden dies, um die Vorlage zu identifizieren, die zum Erstellen der Liste verwendet wurde. Überprüfen Sie auch die Konfigurationseinstellungen und Ansichten, die in Ihrer Liste definiert sind.

  2. Erfahren Sie mehr über Farmlösungen. Weitere Informationen finden Sie unter Erstellen von Farmlösungen in SharePoint.

Suchen nach Listen, die mit einer bestimmten Basisvorlage erstellt wurden

Im folgenden Code zeigt die -Methode, wie Listen gesucht werden, die mithilfe einer bestimmten Basisvorlage erstellt wurden. Diese Methode:

  1. Verwendet clientContext , um alle Listen im aktuellen Web mithilfe von Web.Lists abzurufen. Die Include-Anweisung wird im Lambdaausdruck verwendet, um eine Auflistung von Listen zurückzugeben. Die zurückgegebenen Listen müssen alle über Eigenschaftswerte verfügen, die für BaseTemplate, BaseType und Title angegeben sind.

  2. Wenn list.BaseTemplate gleich 10003 ist, fügt die Liste für jede Liste in der Auflistung der zurückgegebenen Listen mit dem Namen listsToReplace einer Auflistung zu ersetzenden Listen hinzu. Denken Sie daran, dass 10003 der Bezeichner der benutzerdefinierten Listenvorlage war, den wir im Beispiel Contoso.Intranet überprüft haben.

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

    Wichtig

    Im vorherigen Code durchlaufen Sie zuerst die ListCollection, um auszuwählen, welche Listen geändert werden müssen, und rufen dann ReplaceList auf, um die Listen zu ändern. Dieses Muster ist erforderlich, da das Ändern des Inhalts einer Auflistung beim Durchlaufen der Auflistung eine Ausnahme auslöst.

  3. Nach dem Identifizieren einer Liste, die ersetzt werden soll, zeigt ReplaceList die Reihenfolge der Vorgänge an, die zum Ersetzen der Liste ausgeführt werden sollen.

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

Erstellen einer neuen Liste

CreateReplacementList verwendet ListCreationInformation, um eine neue Liste zu erstellen.

Der Titel der neuen Liste wird auf den Titel der vorhandenen Liste festgelegt, an die das Add-In angefügt wird. Die ListTemplateType-Enumeration wird verwendet, um den Vorlagentyp der Liste auf eine Dokumentbibliothek festzulegen. Wenn Sie eine Liste basierend auf einem anderen Vorlagentyp erstellen, stellen Sie sicher, dass Sie den richtigen Vorlagentyp verwenden. Wenn Sie beispielsweise eine Kalenderliste erstellen, verwenden Sie ListTemplateType.Events anstelle von 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;
}

Konfigurieren von Listeneinstellungen

SetListSettings wendet die ursprünglichen Listeneinstellungen wie folgt auf die neue Liste an:

  1. Abrufen verschiedener Listeneinstellungen aus der ursprünglichen Liste.

  2. Anwenden der Listeneinstellung aus der ursprünglichen Liste auf die neue 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();
}

Hinweis

Je nach Ihren Anforderungen können sich die Listeneinstellungen Ihrer ursprünglichen Listen unterscheiden. Überprüfen Sie Ihre Listeneinstellungen, und ändern Sie SetListSettings , um sicherzustellen, dass Ihre ursprünglichen Listeneinstellungen auf Ihre neuen Listen angewendet werden.

Festlegen von Inhaltstypen in der neuen Liste

SetContentTypes legt die Inhaltstypen in der neuen Liste wie folgt fest:

  1. Abrufen von Inhaltstypinformationen aus der ursprünglichen Liste.

  2. Abrufen von Inhaltstypinformationen aus der neuen Liste.

  3. Bestimmen, ob die ursprüngliche Liste Inhaltstypen aktiviert. Wenn die ursprüngliche Liste keine Inhaltstypen aktiviert, wird SetContentTypes beendet. Wenn die ursprüngliche Liste Inhaltstypen aktiviert hat, aktiviert SetContentTypes Inhaltstypen in der neuen Liste mithilfe von newList.ContentTypesEnabled = true.

  4. Durchsuchen Sie für jeden Inhaltstyp in der ursprünglichen Liste die Inhaltstypen in der neuen Liste, um einen übereinstimmenden Inhaltstyp basierend auf dem Namen des Inhaltstyps zu finden, indem Sie newList.ContentTypes.Any(ct = ct)> verwenden. Name == contentType.Name). Wenn der Inhaltstyp nicht in der neuen Liste enthalten ist, wird er der Liste hinzugefügt.

  5. NewList wird ein zweites Mal geladen, da addExistingContentType die Inhaltstypen möglicherweise geändert hat.

  6. Bestimmen Sie für jeden Inhaltstyp in newList anhand von ContentType.Name mithilfe von listToBeReplaced.ContentTypes.Any(ct => ct), ob der Inhaltstyp mit einem Inhaltstyp in der ursprünglichen Liste übereinstimmt. Name == contentType.Name). Wenn keine Übereinstimmung gefunden wird, wird der Inhaltstyp contentTypesToDelete hinzugefügt, um aus der neuen Liste gelöscht zu werden.

  7. Löschen des Inhaltstyps durch Aufrufen von ContentType.DeleteObject.

Hinweis

Wenn Sie einen direkten Transformationsansatz verwenden und Ihre Inhaltstypen deklarativ mithilfe des Featureframeworks bereitgestellt wurden, müssen Sie Folgendes ausführen:

  1. Erstellen Sie neue Inhaltstypen.
  2. Legen Sie den Inhaltstyp für die Listenelemente fest, wenn Sie den Inhalt von der ursprünglichen Liste zur neuen Liste in MigrateContent migrieren.
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();
}

Hinweis

An diesem Punkt kann die neue Liste Inhalte aus der ursprünglichen Liste akzeptieren. Sie können auch optional Ansichten hinzufügen und entfernen.

Hinzufügen oder Entfernen von Ansichten (optional)

Benutzer können in einer Liste definierte Ansichten hinzufügen oder entfernen, um die geschäftlichen Anforderungen zu erfüllen. Aus diesem Grund müssen Sie möglicherweise Ansichten in der neuen Liste hinzufügen oder entfernen.

Hinzufügen von Ansichten zur neuen Liste

AddViews fügt der neuen Liste Ansichten aus der ursprünglichen Liste wie folgt hinzu:

  1. Verwenden von List.Views , um alle Ansichten in der ursprünglichen Liste abzurufen.

  2. Verwenden des Lambdaausdrucks zum Laden verschiedener Ansichtseigenschaften in der Sichtenauflistung .

  3. Erstellen Sie für jede Ansicht in der ursprünglichen Liste eine Ansicht mithilfe von ViewCreationInformation.

    Verschiedene Eigenschaften werden für die neue Ansicht basierend auf Ansichtseigenschaften aus der ursprünglichen Ansicht festgelegt. Die GetViewType-Hilfsmethode wird aufgerufen, um den ViewType der Ansicht zu bestimmen. Die neue Ansicht wird dann der Liste der Ansichten namens viewsToCreate hinzugefügt.

  4. Hinzufügen der Ansichten zur List.Views-Auflistung mithilfe der Add-Methode in der Views-Auflistung der 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;
         }
     }
    

Entfernen von Ansichten aus der neuen Liste

Im folgenden Code entfernt RemoveViews Ansichten aus der neuen Liste wie folgt:

  1. Abrufen der Listenansichten für die neue Liste mithilfe der List.Views-Eigenschaft .

  2. Bestimmen Sie für jede Ansicht in der neuen Liste, ob diese Ansicht nicht in der ursprünglichen Liste vorhanden ist, indem Sie den Titel der Ansicht mithilfe von !listToBeReplaced.Views.Any(v => v.Title == view) abgleichen. Titel. Wenn eine Ansicht in der neuen Liste keine übereinstimmende Ansicht in der ursprünglichen Liste enthält, fügen Sie die Ansicht zu viewsToRemove hinzu.

  3. Löschen aller Ansichten in viewsToRemove mithilfe von 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();
     }
    

Migrieren von Inhalten aus der ursprünglichen Liste zur neuen Liste

MigrateContent migriert den Inhalt aus der ursprünglichen Liste in die neue Liste wie folgt:

  1. Abrufen des Ziels zum Kopieren der Dateien oder des Stammordners der neuen Liste mithilfe von List.RootFolder. Die serverrelative URL des Ziellistenordners wird mithilfe von Folder.ServerRelativeUrl abgerufen.

  2. Abrufen der Quelle der Dateien oder des Stammordners der ursprünglichen Liste mithilfe von List.RootFolder. Die serverrelative URL des Listenordners und alle Dateien im Stammordner der Quelle werden mithilfe des clientContext-Objekts geladen.

  3. Erstellen Sie für jede Datei in der Quelle newUrl, in der die neue URL der Datei gespeichert wird. newUrl wird erstellt, indem der Quellstammordner durch den Stammordner des Ziels ersetzt wird.

  4. Verwenden sie File.CopyTo , um die Datei in die URL des Zielstammordners zu kopieren. Alternativ können Sie die File.MoveTo-Methode verwenden, um die Datei in die Ziel-URL zu verschieben.

Hinweis

Der folgende Code gibt alle Listenelemente zurück. In Ihrer Produktionsumgebung sollten Sie den folgenden Code optimieren, indem Sie eine -Schleife implementieren und mehrere Iterationen verwenden, um kleine Mengen von Listenelementen zu migrieren.

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

Hinweis

Der vorherige Code zeigt, wie Dateien migriert werden, die im Stammordner einer Liste gespeichert sind. Wenn Ihre Liste Unterordner enthält, müssen Sie zusätzlichen Code hinzufügen, um die Unterordner und deren Inhalt zu migrieren. Wenn Ihre Liste Workflows verwendet, ist zusätzlicher Code erforderlich, um den Workflow der neuen Liste zuzuordnen.

Siehe auch