Compartilhar via


Substituir tipos de conteúdo do SharePoint e colunas de site em soluções de farm

Este artigo descreve o processo de transformação a ser usado ao substituir tipos de conteúdo e colunas de site, adicionando colunas de site a novos tipos de conteúdo e substituindo tipos de conteúdo anteriores por novos tipos de conteúdo usando o CSOM (modelo de objeto do lado do cliente do SharePoint).

Importante

As soluções farm não podem ser migradas para o SharePoint Online. Ao aplicar as técnicas e o código descritos neste artigo, você pode criar uma nova solução que usa tipos de conteúdo atualizados e colunas de site e fornece funcionalidades semelhantes às suas soluções farm ou soluções declarativas de área restrita. Em seguida, a nova solução pode ser implantada no SharePoint Online.

O código neste artigo requer código adicional para fornecer uma solução totalmente funcional. Por exemplo, este artigo não discute como autenticar a Office 365, como implementar o tratamento de exceção necessário e assim por diante. Para obter exemplos de código adicionais, consulte o projeto padrões e práticas do desenvolvedor Office 365.

Observação

The code in this article is provided as-is, without warranty of any kind, either express or implied, including any implied warranties of fitness for a particular purpose, merchantability, or non-infringement.

Para substituir tipos de conteúdo e colunas de site usando o CSOM:

  1. Crie um novo tipo de conteúdo.

  2. Crie uma nova coluna de site (também chamada de campo).

  3. Adicione a nova coluna do site ao novo tipo de conteúdo.

  4. Substitua referências antigas de tipo de conteúdo pelo novo tipo de conteúdo.

No código a seguir, Main mostra a ordem das operações a serem executadas para substituir tipos de conteúdo e colunas de site usando o 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);
    }

}

No código a seguir, GetContentTypeByName obtém um tipo de conteúdo do site atual por:

  1. Usando a propriedade Web.ContentTypes para obter um ContentTypeCollection, que é uma coleção de tipos de conteúdo no site atual.

  2. Localizando e retornando um tipo de conteúdo do site, correspondendo o nome do tipo de conteúdo do site ao nome do tipo de conteúdo existente, que é enviado pelo parâmetro de nome .

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

Criar um novo tipo de conteúdo

No código a seguir, CreateContentType cria um novo tipo de conteúdo por:

  1. Criando uma constante chamada contentTypeName para armazenar o nome do tipo de conteúdo. O nome do novo tipo de conteúdo é definido como o nome do tipo de conteúdo anterior.

  2. Chamando GetContentTypeByName para encontrar um tipo de conteúdo correspondente no site.

  3. Se o tipo de conteúdo já existir, nenhuma ação adicional será necessária e o controle retornará ao Main quando o retorno for chamado.

    Se o tipo de conteúdo não existir, as propriedades do tipo de conteúdo serão definidas usando um objeto ContentTypeCreationInformation chamado newCt.

    A nova ID do tipo de conteúdo é atribuída a newCt.Id usando o 0x0101 de ID do tipo de conteúdo do documento base. Para obter mais informações, consulte Hierarquia de Tipo de Conteúdo Base.

  4. Adicionando o novo tipo de conteúdo usando 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();
}

Criar uma nova coluna de site

No código a seguir, CreateSiteColumn cria uma nova coluna de site por:

  1. Criando uma constante chamada fieldName para armazenar o nome do campo. O nome do novo campo é definido como o nome do campo anterior.

  2. Obtendo as colunas do site definidas no site usando a propriedade Web.Fields .

  3. Encontrar um campo correspondente no site correspondendo os nomes de campo no site ao fieldName. Se o campo já existir, nenhuma ação adicional será necessária e o controle retornará para Main quando o retorno for chamado. Se o campo não existir, uma cadeia de caracteres CAML especificando o esquema de campo será atribuída a FieldAsXML e, em seguida, o campo será criado usando 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();
}

Adicionar a nova coluna do site ao novo tipo de conteúdo

No código a seguir, AddSiteColumnToContentType cria uma conexão entre o tipo de conteúdo e o campo por:

  1. Carregando o tipo de conteúdo e, em seguida, o campo faz referência a esse tipo de conteúdo usando a propriedade ContentType.FieldLinks .

  2. Carregando o campo.

  3. Determinar se o tipo de conteúdo se refere ao campo usando contentType.FieldLinks.Any(f => f.Name == fieldName) para corresponder no nome do campo.

  4. Se o tipo de conteúdo já se referir ao campo, nenhuma ação adicional será necessária e o controle retornará para Main quando o retorno for chamado. Se o tipo de conteúdo não se referir ao campo, as propriedades de referência de campo serão definidas em um objeto FieldLinkCreationInformation .

  5. Adicionando o objeto FieldLinkCreationInformation à propriedade 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();
}

Substituir referências antigas de tipo de conteúdo pelo novo tipo de conteúdo

No código a seguir, ReplaceContentType verifica todos os itens em todas as bibliotecas em busca de conteúdo que faça referência ao tipo de conteúdo antigo e, em seguida, substitui essas referências pelo novo tipo de conteúdo (ContosoDocumentByCSOM) por:

  1. Atribuindo a ID do tipo de conteúdo antiga a uma constante.

  2. Obtendo o novo tipo de conteúdo usando GetContentTypeByName.

  3. Obtendo todas as listas no site usando Web.Lists.

  4. Carregando todas as listas no site e todos os tipos de conteúdo em cada lista usando cc.Load(lists, l => l.Include(list => list= list. ContentTypes).

  5. Para cada lista retornada, pesquise os tipos de conteúdo da lista para corresponder a um tipo de conteúdo com a ID do tipo de conteúdo antiga usando a lista. ContentTypes.Any(c => c.StringId.StartsWith(oldContentTypeId))). Se uma correspondência for encontrada, a lista com o tipo de conteúdo antigo será adicionada a listagemWithContentType.

  6. Para cada lista em listasWithContentType:

  7. Determinando se o novo tipo de conteúdo está anexado à lista. Se o novo tipo de conteúdo não estiver anexado à lista, use ContentTypeCollection.AddExistingContentType para anexar o novo tipo de conteúdo à lista.

  8. Obtendo todos os itens de lista na lista.

  9. Para cada item de lista, obter a ID do tipo de conteúdo do item de lista. Determine se a ID do tipo de conteúdo do item de lista é igual à ID do tipo de conteúdo antigo. Se as IDs do tipo de conteúdo não forem iguais, pule para o próximo item da lista. Se as IDs do tipo de conteúdo forem iguais, use ContentType.StringId para atribuir a nova ID do tipo de conteúdo ao item de lista.

Observação

O tipo de conteúdo antigo ainda está na lista, mas não é mais usado. Agora você pode excluir o tipo de conteúdo antigo das listas e, em seguida, retirá-lo. Este artigo descreve apenas como substituir tipos de conteúdo de documento. Se você estiver substituindo tipos de conteúdo em layouts de página, certifique-se de atualizar a propriedade AssociatedContentType em cada layout de página na coleção 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();
    }
}

Confira também