Partilhar via


Adicionar lógica de primeira execução ao suplemento hospedado pelo provedor

Este é o oitavo de uma série de artigos sobre os conceitos básicos do desenvolvimento de suplementos do SharePoint hospedados pelo provedor. Primeiro, você deve estar familiarizado com suplementos do SharePoint e os artigos anteriores desta série, que podem ser encontrados em Introdução à criação de suplementos do SharePoint hospedados pelo provedor.

Observação

Se você trabalhou com esta série sobre suplementos hospedados pelo provedor, você terá uma solução do Visual Studio que pode ser usada para continuar com este tópico. Você também pode baixar o repositório em SharePoint_Provider-hosted_Add-Ins_Tutorials e abrir o arquivo BeforeFirstRunLogic.sln.

Neste artigo, você adiciona código à página inicial do Suplemento do SharePoint da Chain Store que verifica se a instância atual do suplemento está sendo executada pela primeira vez. Se for a primeira vez, o código implantará a lista Funcionários Locais e o botão de faixa de opções personalizado.

Criar a classe básica para implantar componentes do SharePoint

Observação

As configurações de Projetos de Inicialização no Visual Studio tendem a reverter para padrões sempre que a solução é reaberta. Sempre siga estas etapas imediatamente após a reabertura da solução de exemplo nesta série de artigos:

  1. Clique com botão direito do mouse no nó da solução na parte superior do Gerenciador de Soluções e então selecione Definir Projetos de Inicialização.
  2. Verifique se todos os três projetos estão definidos como Iniciar na coluna Ação.
  1. No projeto ChainStoreWeb no Gerenciador de Soluções, clique com o botão direito do mouse na pasta Utilitários e selecione Adicionar>Item Existente.

  2. Em Explorador de Arquivos, vá para a pasta solução, a pasta ChainStoreWeb e abra a pasta Utilitários.

  3. Selecione SharePointComponentDeployer.cs e selecione Adicionar.

  4. Abra o arquivo SharePointComponentDeployer.cs. Ele tem uma classe estática e dois métodos estáticos que obtêm e definem a versão do suplemento na tabela Locatários do banco de dados corporativo. Não discutiremos esses métodos porque esta série de artigos não se destina a ensinar ASP.NET ou SQL Server/programação do Azure.

  5. Adicione as instruções de uso a seguir à parte superior do arquivo.

      using System.Web;
      using System.Linq;
      using System.Collections.Generic;
      using Microsoft.SharePoint.Client;
    
  6. Na parte superior da SharePointComponentDeployer classe, adicione os dois campos estáticos a seguir. Ambos são inicializados no método Page_Load da página inicial do suplemento (você adiciona esse código em uma etapa posterior).

      internal static SharePointContext sPContext;
      internal static Version localVersion;
    

    Observe o seguinte sobre este código:

    • O primeiro campo contém o SharePointContext objeto necessário para fazer operações CRUD no SharePoint.

    • O segundo campo contém o número de versão do suplemento instalado na Web do host. Esse valor é inicialmente diferente do valor padrão (0000.0000.0000.0000) registrado na tabela Locatários corporativos quando o manipulador de instalação registra o locatário. Por exemplo, a primeira versão do suplemento será 1.0.0.0.

  7. Crie a propriedade estática a seguir para manter a versão do suplemento que está atualmente registrada na tabela Locatários corporativos . Ele usa os dois métodos que já estavam no arquivo para obter e definir esse valor.

      internal static Version RemoteTenantVersion
    {
        get
        {
            return GetTenantVersion();
        }
        set
        {
            SetTenantVersion(value);
        }
    }
    
  8. Agora crie a propriedade a seguir IsDeployed .

      public static bool IsDeployed
    {
        get
        {
            if (RemoteTenantVersion < localVersion)
                return false; 
            else
                return true; 
        }
    }
    

    Observe o seguinte sobre este código:

    • O método Page_Load da página inicial do suplemento usa o valor dessa propriedade para determinar se o suplemento está em execução pela primeira vez. Um valor falso sinaliza que o suplemento não foi executado antes na Web do host atual, portanto, seus componentes precisam ser implantados.

    • O critério é se o número de versão registrado na tabela Locatários é menor do que a versão realmente instalada. Na primeira vez que o suplemento é executado, ele é menor. O código que você grava em uma etapa posterior define a versão na tabela Locatários como a mesma versão que está realmente instalada, portanto, quando o suplemento é executado novamente, IsDeployed retorna true e a lógica de implantação não é executada novamente.

  9. Adicione o método a seguir à classe SharePointComponentDeployer. Observe que a última coisa que o método faz é atualizar a versão de locatário registrada no banco de dados corporativo (0000.0000.0000.0000) para corresponder à versão real do suplemento na Web do host (1.0.0.0). Você concluirá esse método em uma etapa posterior.

      internal static void DeployChainStoreComponentsToHostWeb(HttpRequest request)
    {
        // TODO4: Deployment code goes here.
    
        RemoteTenantVersion = localVersion;
    }
    

Observação

Você pode se perguntar agora por que o suplemento usa números de versão e um teste "menor que" para determinar a resposta a uma pergunta simples sim/não: "O suplemento está em execução pela primeira vez?" Poderíamos muito bem ter um campo de cadeia de caracteres simples na tabela Locatários que está definido como ainda não executado no manipulador de instalação e, em seguida, alterado para já executado uma vez pela lógica de primeira execução depois que os componentes do SharePoint são implantados.

Para o suplemento Chain Store, um teste simples funcionaria. No entanto, geralmente é uma boa prática usar números de versão porque é provável que um suplemento de produção seja atualizado no futuro; ou seja, atualizado depois que ele já está instalado. Quando essa hora chegar, sua lógica de suplemento precisa ser sensível a mais do que as duas possibilidades ainda não executadas e já executadas uma vez.

Suponha, por exemplo, que você queira adicionar uma lista adicional à Web host na atualização da versão 1.0.0.0 para 2.0.0.0. Você pode fazer isso em um manipulador de eventos de atualização ou na lógica de primeira execução após atualização. De qualquer forma, sua lógica de implantação precisa implantar novos componentes, mas também precisa evitar tentar reimplantar componentes que foram implantados em uma versão anterior do suplemento. Um número de versão de 1.0.0.0 sinaliza que os componentes da versão 1.0.0.0 foram implantados, mas que a lógica de primeira execução após atualização ainda não foi executada.

Adicionar a lógica de inicialização básica

A Web do host do SharePoint precisa informar ao aplicativo Web remoto qual versão do suplemento ele instalou. Usamos um parâmetro de consulta para fazer isso.

  1. Abra o arquivo AppManifest.xml no projeto ChainStore . No designer, você vê o espaço reservado {StandardTokens} como o valor da caixa de cadeia de caracteres Consulta . Adicione a cadeia de caracteres "&amp;SPAddInVersion=1.0.0.0" ao final.

    O designer de manifesto deve ser semelhante ao seguinte. Observe que o número da versão que você passa na cadeia de caracteres de consulta precisa corresponder ao valor na caixa Versão do designer. Se você atualizar o suplemento, uma de suas tarefas será gerar esses dois valores e mantê-los iguais.

    Figura 1. Guia geral do designer de manifesto

    A guia Geral do designer de manifesto. A caixa Versão tem o valor zero zero zero. A caixa de cadeia de caracteres Query diz

  2. Abra o arquivo CorporateDataViewer.aspx.cs e adicione o código a seguir ao método Page_Load , logo abaixo da linha que inicializa o spContext objeto.

     SharePointComponentDeployer.sPContext = spContext;
     SharePointComponentDeployer.localVersion = new Version(Request.QueryString["SPAddInVersion"]);
    
     if (!SharePointComponentDeployer.IsDeployed)
     {
         SharePointComponentDeployer.DeployChainStoreComponentsToHostWeb(Request);
     }
    

    Observe o seguinte sobre este código:

    • Ele começa definindo os dois campos estáticos na classe estática SharePointComponentDeployer . Ele passa o objeto SharePointContext porque o código nas chamadas para o SharePointComponentDeployer SharePoint e usa o parâmetro de consulta que você adicionou para definir a localVersion propriedade.

    • Ele não faz nada se IsDeployed for verdade; ou seja, se a lógica de primeira execução já tiver sido executada. Caso contrário, ele chama o método de implantação e passa o objeto ASP.NET Solicitar .

Implantar programaticamente uma lista do SharePoint

  1. No arquivo SharePointComponentDeployer.cs, substitua o TODO4 pela linha a seguir (você cria esse método na próxima etapa).

      CreateLocalEmployeesList();
    
  2. Adicione o método a seguir à classe SharePointComponentDeployer.

      private static void CreateLocalEmployeesList()
    {
        using (var clientContext = sPContext.CreateUserClientContextForSPHost())
        {
            var query = from list in clientContext.Web.Lists
                        where list.Title == "Local Employees"
                        select list;
            IEnumerable<List> matchingLists = clientContext.LoadQuery(query);
            clientContext.ExecuteQuery();
    
            if (matchingLists.Count() == 0)
            {
               // TODO5: Create the list 
    
               // TODO6: Rename the Title field on the list 
    
               // TODO7: Add "Added to Corporate DB" field to the list 
    
               clientContext.ExecuteQuery();
            }
        }
    }
    

    Observe o seguinte sobre este código:

    • Ele tem duas chamadas de ExecuteQuery. O primeiro é necessário para determinar se a lista já existe. O segundo faz o trabalho de criar a lista.

    • O método ClientContext.LoadQuery é semelhante ao método ClientContext.Load , exceto que, em vez de trazer uma entidade como uma lista para o cliente, ele reduz os resultados enumeráveis de uma consulta.

  3. Substitua TODO5 pelo código a seguir.

      ListCreationInformation listInfo = new ListCreationInformation();
      listInfo.Title = "Local Employees";
      listInfo.TemplateType = (int)ListTemplateType.GenericList;
      listInfo.Url = "Lists/Local Employees";
      List localEmployeesList = clientContext.Web.Lists.Add(listInfo);
    

    Observe o seguinte sobre este código:

    • A classe ListCreationInformation é semelhante à classe ListItemCreationInformation que você viu em um artigo anterior nesta série. É uma classe leve mais adequada para enviar informações do aplicativo Web para o SharePoint do que a classe Lista completa.

    • Há muitos tipos de modelos de lista, como o tipo Tarefas para uma lista de "fazer" e o tipo Eventos para um calendário. A lista Funcionários Locais baseia-se na mais simples: o tipo genérico.

    • A propriedade ListCreationInformation.Url contém a URL da lista relativa à Web do host. Ao especificar , o código está definindo "Lists/LocalEmployees"a URL completa da lista como https://{SharePointDomain}/hongkong/_layouts/15/start.aspx#/Lists/Local%20Employees.

  4. Substitua TODO6 pelo código a seguir, que altera o nome público do campo "Título" (coluna) de "Título" para "Nome". Isso é o que você fez na página Configurações de Lista quando criou a lista manualmente.

      Field field = localEmployeesList.Fields.GetByInternalNameOrTitle("Title");
      field.Title = "Name";
      field.Update();
    
  5. Você também criou manualmente um campo chamado Adicionado ao BD Corporativo. Para fazer isso programaticamente, adicione o código a seguir no lugar de TODO7.

          localEmployeesList.Fields.AddFieldAsXml("<Field DisplayName='Added to Corporate DB'"
                                                 +"Type='Boolean'>"
                                                 + "<Default>FALSE</Default></Field>",
                                                 true,
                                                 AddFieldOptions.DefaultValue);
    

    Observe o seguinte sobre este código:

    • As principais propriedades do campo são especificadas com um blob XML. Esse é um legado da arquitetura do SharePoint, em que sites, listas, campos, tipos de conteúdo e a maioria dos outros tipos de componentes do SharePoint são definidos como XML. Nesse caso, especificamos o nome de exibição, o tipo de dados e o valor padrão do campo.

    • O segundo parâmetro determina se o campo está visível na exibição padrão da lista. Definimos como true.

    • O terceiro parâmetro determina a quais tipos de conteúdo o campo é adicionado. Passar DefaultValue significa que ele só é adicionado ao tipo de conteúdo padrão da lista.

  6. Lembre-se de que o DB corporativo adicionado é Não (ou seja, falso) por padrão, mas o botão de faixa de opções personalizado no suplemento define-o como Sim depois que ele adiciona o funcionário ao banco de dados corporativo. Esse sistema funciona melhor somente se os usuários não puderem alterar manualmente o valor do campo. Para garantir que não o façam, torne o campo invisível nos formulários para criar e editar itens na lista Funcionários Locais . Fazemos isso adicionando mais dois atributos ao primeiro parâmetro, conforme mostrado no código a seguir.

      localEmployeesList.Fields.AddFieldAsXml("<Field DisplayName='Added to Corporate DB'" 
                                             + " Type='Boolean'"  
                                             + " ShowInEditForm='FALSE' "
                                             + " ShowInNewForm='FALSE'>"
                                             + "<Default>FALSE</Default></Field>",
                                             true,
                                             AddFieldOptions.DefaultValue);
    
  7. O todo CreateLocalEmployeesList agora deve se parecer com o seguinte.

           private static void CreateLocalEmployeesList()
         {
             using (var clientContext = sPContext.CreateUserClientContextForSPHost())
             {
                 var query = from list in clientContext.Web.Lists
                             where list.Title == "Local Employees"
                             select list;
                 IEnumerable<List> matchingLists = clientContext.LoadQuery(query);
                 clientContext.ExecuteQuery();
    
                 if (matchingLists.Count() == 0)
                 {
                     ListCreationInformation listInfo = new ListCreationInformation();
                     listInfo.Title = "Local Employees";
                     listInfo.TemplateType = (int)ListTemplateType.GenericList;
                     listInfo.Url = "LocalEmployees";
                     List localEmployeesList = clientContext.Web.Lists.Add(listInfo);
    
                     Field field = localEmployeesList.Fields.GetByInternalNameOrTitle("Title");
                     field.Title = "Name";
                     field.Update();
    
                     localEmployeesList.Fields.AddFieldAsXml("<Field DisplayName='Added to Corporate DB'" 
                                                             + " Type='Boolean'"  
                                                            + " ShowInEditForm='FALSE' "
                                                            + " ShowInNewForm='FALSE'>"
                                                            + "<Default>FALSE</Default></Field>",
                                                             true,
                                                             AddFieldOptions.DefaultValue);
                     clientContext.ExecuteQuery();
                 }
             }
         }
    

Remover temporariamente o botão personalizado do projeto

Por razões técnicas que discutiremos no próximo artigo, o botão personalizado que criamos não pode ser instalado sem modificação quando está sendo colocado na faixa de opções de uma lista que é implantada programaticamente. Vamos removê-lo temporariamente do projeto para que possamos testar nossa lógica de primeira execução. Vamos trazê-lo de volta no próximo artigo.

  • Em Gerenciador de Soluções, no projeto ChainStore, clique com o botão direito do mouse no nó AddEmployeeToCorpDB e selecione Excluir do Project.

Solicitar permissão para gerenciar listas na Web do host

Como o suplemento agora adiciona uma lista à Web do host, não apenas itens a uma lista existente, precisamos escalar as permissões que o suplemento solicita de Gravar para Gerenciar:

  1. Em Gerenciador de Soluções, abra o arquivo AppManifest.xml no projeto ChainStore.

  2. Na guia Permissões , deixe o valor escopo na Web, mas no campo Permissão , selecione Gerenciar na lista suspensa.

  3. Salve o arquivo.

Execute o suplemento e teste a lógica de primeira execução

  1. Abra a página Conteúdo do Site do site da loja de Hong Kong e remova a lista Funcionários Locais .

  2. Use a tecla F5 para implantar e executar o suplemento. O Visual Studio hospeda o aplicativo Web remoto no IIS Express e hospeda o banco de dados SQL no SQL Express. Ele também faz uma instalação temporária do suplemento em seu site de teste do SharePoint e executa imediatamente o suplemento. Você é solicitado a conceder permissões ao suplemento antes que sua página inicial seja aberta.

  3. Quando a página inicial do suplemento for aberta, selecione o link Voltar para Site no controle cromado na parte superior.

  4. Acesse a página Conteúdo do site. A lista Funcionários Locais está presente porque sua lógica de primeira execução a adicionou.

    Observação

    Se a lista não estiver lá ou você tiver outras indicações de que o código de primeira execução não está sendo executado, pode ser que a tabela Locatários não esteja sendo revertida para um estado vazio quando você selecionar F5. A causa mais comum disso é que o projeto ChainCorporateDB não é mais definido como um projeto de inicialização no Visual Studio. Consulte a nota próxima à parte superior deste artigo para saber como corrigir isso. Certifique-se também de que você configurou o banco de dados a ser reconstruído conforme descrito em Configurar o Visual Studio para reconstruir o banco de dados corporativo a cada sessão de depuração.

  5. Abra a lista e adicione um item. Observe que, no novo formulário de item, o campo Adicionado ao BD Corporativo não está mais presente, portanto, não pode ser definido manualmente. Isso também vale para o formulário de item de edição.

    Figura 2. Novo formulário de item para a lista Funcionários Locais

    O novo formulário de item para a lista Funcionários Locais. O campo

  6. Use o botão de volta do navegador para voltar para a página inicial do suplemento.

  7. Selecione o ícone de engrenagem no controle cromado na parte superior e selecione Configurações da conta.

  8. Na página Configurações da conta , selecione o botão Mostrar Versão de Suplemento . A versão é exibida como 1.0.0.0 porque a lógica de primeira execução a alterou.

    Figura 3. Página configurações da conta

    A página de configurações de Conta com o número de versão 1.0.0.0.

  9. Para encerrar a sessão de depuração, feche a janela do navegador ou interrompa a depuração no Visual Studio. Sempre que você seleciona F5, o Visual Studio retrai a versão anterior do suplemento e instala a mais recente.

  10. Você lidará com esse suplemento e com a solução do Visual Studio em outros artigos, e recomenda-se retirar o suplemento uma última vez quando for deixar de trabalhar com ele por algum tempo. Clique com botão direito do mouse no projeto no Gerenciador de Soluções e escolha Retirar.

Próximas etapas

No próximo artigo, você verá como obter o botão personalizado para a faixa de opções Funcionário Local de volta ao suplemento agora que a lista está sendo implantada de forma programática: implantar programaticamente um botão personalizado no suplemento hospedado pelo provedor.