Remplacer les SharePoint de contenu et les colonnes de site dans les solutions de batterie de serveurs

Cet article décrit le processus de transformation à utiliser lors du remplacement des types de contenu et des colonnes de site, de l’ajout de colonnes de site à de nouveaux types de contenu, puis du remplacement des types de contenu précédents par de nouveaux types de contenu à l’aide du modèle objet côté client SharePoint (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 qui utilise des colonnes de site et des types de contenu mis à jour et fournit des fonctionnalités similaires à vos solutions de batterie de serveurs ou solutions bac à sable déclaratives. La nouvelle solution peut ensuite être déployée sur SharePoint Online.

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.

Pour remplacer les types de contenu et les colonnes de site à l’aide du modèle CSOM :

  1. Créez un type de contenu.

  2. Créez une colonne de site (également appelée champ).

  3. Ajoutez la nouvelle colonne de site au nouveau type de contenu.

  4. Remplacez les anciennes références de type de contenu par le nouveau type de contenu.

Dans le code suivant, Main indique l’ordre des opérations à effectuer pour remplacer les types de contenu et les colonnes de site à l’aide du modèle CSOM.

static void Main(string[] args)
{
    using (var clientContext = new ClientContext("http://contoso.sharepoint.com"))
    {

        Web web = clientContext.Web;
        
        CreateContentType(clientContext, web);
        CreateSiteColumn(clientContext, web);
        AddSiteColumnToContentType(clientContext, web);

        // Replace the old content type with the new content type.
        ReplaceContentType(clientContext, web);
    }

}

Dans le code suivant, GetContentTypeByName obtient un type de contenu du site actuel en :

  1. Utilisation de la propriété Web.ContentTypes pour obtenir un ContentTypeCollection, qui est une collection de types de contenu sur le site actuel.

  2. Recherche et renvoi d’un type de contenu à partir du site, en faisant correspondre le nom du type de contenu de site au nom du type de contenu existant, qui est envoyé par le paramètre name.

    private static ContentType GetContentTypeByName(ClientContext cc, Web web, string name)
    {
        ContentTypeCollection contentTypes = web.ContentTypes;
        cc.Load(contentTypes);
        cc.ExecuteQuery();
        return contentTypes.FirstOrDefault(o => o.Name == name);
    }

Créer un type de contenu

Dans le code suivant, CreateContentType crée un type de contenu en :

  1. Création d’une constante appelée contentTypeName pour stocker le nom du type de contenu. Le nom du nouveau type de contenu est celui du type de contenu précédent.

  2. Appel de GetContentTypeByName pour rechercher un type de contenu correspondant sur le site.

  3. Si le type de contenu existe déjà, aucune action supplémentaire n’est nécessaire et le contrôle est revenir à Main lorsque le retour est appelé.

    Si le type de contenu n’existe pas, les propriétés du type de contenu sont définies à l’aide d’un objet ContentTypeCreationInformation appelé newCt.

    Le nouvel ID de type de contenu est affecté à newCt.Id à l’aide de l’ID de type de contenu de document de base 0x0101. Pour plus d’informations, voir Hiérarchie des types de contenu de base.

  4. Ajout du nouveau type de contenu à l’aide de ContentTypeCollection.Add.

private static void CreateContentType(ClientContext cc, Web web)
{
    // The new content type will be created using this name.
    const string contentTypeName = "ContosoDocumentByCSOM";

    // Determine whether the content type already exists.
    var contentType = GetContentTypeByName(cc, web, contentTypeName);

    // The content type exists already. No further action required.
    if (contentType != null) return;

    // Create the content type using the ContentTypeInformation object.
    ContentTypeCreationInformation newCt = new ContentTypeCreationInformation();
    newCt.Name = "ContosoDocumentByCSOM";

    // Create the new content type based on the out-of-the-box document (0x0101) and assign the ID to the new content type.
    newCt.Id = "0x0101009189AB5D3D2647B580F011DA2F356FB2";

    // Assign the content type to a specific content type group.
    newCt.Group = "Contoso Content Types";

    ContentType myContentType = web.ContentTypes.Add(newCt);
    cc.ExecuteQuery();
}

Créer une colonne de site

Dans le code suivant, CreateSiteColumn crée une colonne de site en :

  1. Création d’une constante appelée fieldName pour stocker le nom du champ. Le nom du nouveau champ est celui du champ précédent.

  2. Obtention des colonnes de site définies sur le site à l’aide de la propriété Web.Fields.

  3. Recherche d’un champ correspondant sur le site en faisant correspondre les noms de champ sur le site à fieldName. Si le champ existe déjà, aucune action supplémentaire n’est nécessaire et le contrôle est revenir à Main lors de l’appel du retour. Si le champ n’existe pas, une chaîne CAML spécifiant le schéma de champ est affectée à FieldAsXML, puis le champ est créé à l’aide de FieldCollection.AddFieldAsXml.

private static void CreateSiteColumn(ClientContext cc, Web web)
{
    // The new field will be created using this name.
    const string fieldName = "ContosoStringCSOM";

    // Load the list of fields on the site.
    FieldCollection fields = web.Fields;
    cc.Load(fields);
    cc.ExecuteQuery();

    // Check fields on the site for a match.
    var fieldExists = fields.Any(f => f.InternalName == fieldName);

     // The field exists already. No further action required.    
    if (fieldExists) return;

    // Field does not exist, so create the new field.
    string FieldAsXML = @"<Field ID='{CB8E24F6-E1EE-4482-877B-19A51B4BE319}' 
                                Name='" + fieldName + @"' 
                                DisplayName='Contoso String by CSOM' 
                                Type='Text' 
                                Hidden='False' 
                                Group='Contoso Site Columns' 
                                Description='Contoso Text Field' />";
    Field fld = fields.AddFieldAsXml(FieldAsXML, true, AddFieldOptions.DefaultValue);
    cc.ExecuteQuery();
}

Ajouter la nouvelle colonne de site au nouveau type de contenu

Dans le code suivant, AddSiteColumnToContentType crée une connexion entre le type de contenu et le champ par :

  1. Chargement du type de contenu, puis le champ référence ce type de contenu à l’aide de la propriété ContentType.FieldLinks.

  2. Chargement du champ.

  3. Déterminer si le type de contenu fait référence au champ à l’aide de contentType.FieldLinks.Any(f => f.Name == fieldName) pour correspondre au nom du champ.

  4. Si le type de contenu fait déjà référence au champ, aucune action supplémentaire n’est nécessaire et le contrôle est revenir à Main lorsque le retour est appelé. Si le type de contenu ne fait pas référence au champ, les propriétés de référence de champ sont définies sur un objet FieldLinkCreationInformation.

  5. Ajout de l’objet FieldLinkCreationInformation à la propriété ContentType.FieldLinks.

private static void AddSiteColumnToContentType(ClientContext cc, Web web)
{
    // The name of the content type. 
    const string contentTypeName = "ContosoDocumentByCSOM";
    // The field name.
    const string fieldName = "ContosoStringCSOM";

    // Load the content type.
    var contentType = GetContentTypeByName(cc, web, contentTypeName);
    if (contentType == null) return; // content type was not found

    // Load field references in the content type.
    cc.Load(contentType.FieldLinks);
    cc.ExecuteQuery();

    // Load the new field.
    Field fld = web.Fields.GetByInternalNameOrTitle(fieldName);
    cc.Load(fld);
    cc.ExecuteQuery();

    // Determine whether the content type refers to the field.
    var hasFieldConnected = contentType.FieldLinks.Any(f => f.Name == fieldName);

    // A reference exists already, no further action is required.
    if (hasFieldConnected) return;

    // The reference does not exist, so we have to create the reference.
    FieldLinkCreationInformation link = new FieldLinkCreationInformation();
    link.Field = fld;
    contentType.FieldLinks.Add(link);
    contentType.Update(true);
    cc.ExecuteQuery();
}

Remplacer les anciennes références de type de contenu par le nouveau type de contenu

Dans le code suivant, ReplaceContentType vérifie tous les éléments de toutes les bibliothèques pour le contenu qui fait référence à l’ancien type de contenu, puis remplace ces références par le nouveau type de contenu (ContosoDocumentByCSOM) par :

  1. Affectation de l’ancien ID de type de contenu à une constante.

  2. Obtention du nouveau type de contenu à l’aide de GetContentTypeByName.

  3. Obtention de toutes les listes sur le site à l’aide de Web.Lists.

  4. Chargement de toutes les listes sur le site et de tous les types de contenu de chaque liste à l’aide de cc.Load(lists, l => l.Include(list => list. ContentTypes).

  5. Pour chaque liste renvoyée, recherchez les types de contenu de la liste pour faire correspondre un type de contenu à l’ancien ID de type de contenu à l’aide de la liste. ContentTypes.Any(c => c.StringId.StartsWith(oldContentTypeId)). Si une correspondance est trouvée, la liste avec l’ancien type de contenu est ajoutée à listsWithContentType.

  6. Pour chaque liste dans listsWithContentType:

  7. Déterminer si le nouveau type de contenu est attaché à la liste. Si le nouveau type de contenu n’est pas attaché à la liste, utilisez ContentTypeCollection.AddExistingContentType pour attacher le nouveau type de contenu à la liste.

  8. Obtention de tous les éléments de liste de la liste.

  9. Pour chaque élément de liste, obtenir l’ID de type de contenu de l’élément de liste. Déterminez si l’ID de type de contenu de l’élément de liste est égal à l’ancien ID de type de contenu. Si les ID de type de contenu ne sont pas égaux, passez à l’élément de liste suivant. Si les ID de type de contenu sont égaux, utilisez ContentType.StringId pour affecter le nouvel ID de type de contenu à l’élément de liste.

Notes

L’ancien type de contenu figure toujours dans la liste, mais il n’est plus utilisé. Vous pouvez désormais supprimer l’ancien type de contenu des listes, puis le retirer. Cet article explique comment remplacer uniquement les types de contenu de document. Si vous remplacez les types de contenu sur les mises en page, veillez à mettre à jour la propriété AssociatedContentType sur chaque mise en page de la collection de sites.

private static void ReplaceContentType(ClientContext cc, Web web)
{
    // The old content type. 
    const string oldContentTypeId = "0x010100C32DDAB6381C44868DCD5ADC4A5307D6";
    // The new content type name.
    const string newContentTypeName = "ContosoDocumentByCSOM";

    // Get the new content type and lists on the site.
    ContentType newContentType = GetContentTypeByName(cc, web, newContentTypeName);
    ListCollection lists = web.Lists;
    
    // Load the new content type and the content types on all lists on the site. 
    cc.Load(newContentType);
    cc.Load(lists,
            l => l.Include(list => list.ContentTypes));
    cc.ExecuteQuery();
    var listsWithContentType = new List<List>();
    foreach (List list in lists)
    {
        bool hasOldContentType = list.ContentTypes.Any(c => c.StringId.StartsWith(oldContentTypeId));
        if (hasOldContentType)
        {
            listsWithContentType.Add(list);
        }
    }
    foreach (List list in listsWithContentType)
    {
        // Determine whether the new content type is already attached to the list.
        var listHasContentTypeAttached = list.ContentTypes.Any(c => c.Name == newContentTypeName);
        if (!listHasContentTypeAttached)
        {
            // Attach content type to list.
            list.ContentTypes.AddExistingContentType(newContentType);
            cc.ExecuteQuery();
        }
        // Get all list items.
        CamlQuery query = CamlQuery.CreateAllItemsQuery();
        ListItemCollection items = list.GetItems(query);
        cc.Load(items);
        cc.ExecuteQuery();

        // For each list item, determine whether the old content type is used, and then update to the new content type. 
        foreach (ListItem listItem in items)
        {
            // Get the current content type for this list item.
            var currentContentTypeId = listItem["ContentTypeId"] + "";
            var isOldContentTypeAssigned = currentContentTypeId.StartsWith(oldContentTypeId);

            // This item does not use the old content type - skip to next list item.
            if (!isOldContentTypeAssigned) continue;

            // Update the list item content type to the new content type.
            listItem["ContentTypeId"] = newContentType.StringId; // new content type Id;
            listItem.Update();
        }
        // Save all changes.
        cc.ExecuteQuery();
    }
}

Voir aussi