Desenvolver as Funções do Azure com o Visual Studio

O Visual Studio permite desenvolver, testar e implantar funções de biblioteca de classes C# no Azure. Se esta experiência for a sua primeira com o Azure Functions, consulte Uma introdução ao Azure Functions.

Para começar imediatamente, considere concluir o início rápido do Functions para Visual Studio.

Este artigo fornece detalhes sobre como usar o Visual Studio para desenvolver funções de biblioteca de classes C# e publicá-las no Azure. Há dois modelos para desenvolver funções de biblioteca de classes C#: o modelo de trabalhador isolado e o modelo em processo.

Você está lendo a versão do modelo de trabalhador isolado neste artigo. Pode escolher o seu modelo preferido no topo do artigo.

Você está lendo a versão do modelo em processo neste artigo. Pode escolher o seu modelo preferido no topo do artigo.

Salvo indicação em contrário, os procedimentos e exemplos mostrados são para o Visual Studio 2022. Para obter mais informações sobre as versões do Visual Studio 2022, consulte as notas de versão ou as notas de versão de visualização.

Pré-requisitos

  • Visual Studio 2022, incluindo a carga de trabalho de desenvolvimento do Azure.

  • Outros recursos necessários, como uma conta de Armazenamento do Azure, são criados em sua assinatura durante o processo de publicação.

  • Se não tiver uma subscrição do Azure, crie uma conta gratuita do Azure antes de começar.

Criar um projeto das Funções do Azure

O modelo de projeto do Azure Functions no Visual Studio cria um projeto de biblioteca de classes C# que você pode publicar em um aplicativo de função no Azure. Você pode usar um aplicativo de função para agrupar funções como uma unidade lógica para facilitar o gerenciamento, a implantação, o dimensionamento e o compartilhamento de recursos.

  1. No menu Visual Studio, selecione Arquivo>Novo>Projeto.

  2. Em Criar um novo projeto, insira funções na caixa de pesquisa, escolha o modelo Azure Functions e selecione Avançar.

  3. Em Configurar seu novo projeto, insira um nome de projeto para seu projeto e selecione Criar. O nome da aplicação de funções deve ser válido como um espaço de nomes C#. Portanto, não use sublinhados, hífenes ou outros carateres não alfanuméricos.

  4. Para criar uma nova configuração do aplicativo Azure Functions, use os valores na tabela a seguir:

    Definição valor Description
    Versão .NET .NET 6 isolado Esse valor cria um projeto de função que é executado em um processo de trabalho isolado. O processo de trabalho isolado suporta outra versão não-LTS do .NET e também do .NET Framework. Para obter mais informações, consulte Visão geral das versões de tempo de execução do Azure Functions.
    Modelo de função Acionador HTTP Esse valor cria uma função acionada por uma solicitação HTTP.
    Conta de armazenamento (AzureWebJobsStorage) Emulador de armazenamento Como um aplicativo de função no Azure requer uma conta de armazenamento, uma é atribuída ou criada quando você publica seu projeto no Azure. Um gatilho HTTP não usa uma cadeia de conexão de conta de Armazenamento do Azure; todos os outros tipos de gatilho exigem uma cadeia de conexão de conta de Armazenamento do Azure válida.
    Nível de autorização Anônimo A função criada pode ser acionada por qualquer cliente sem fornecer uma chave. Esta definição de autorização torna mais fácil testar a função nova. Para obter mais informações sobre chaves e autorização, consulte Chaves de autorização e Ligações HTTP e webhook.

    Screenshot of Azure Functions project settings

    Definição valor Description
    Versão .NET .NET 6 Esse valor cria um projeto de função que é executado em processo com a versão 4.x do tempo de execução do Azure Functions. Para obter mais informações, consulte Visão geral das versões de tempo de execução do Azure Functions.
    Modelo de função Acionador HTTP Esse valor cria uma função acionada por uma solicitação HTTP.
    Conta de armazenamento (AzureWebJobsStorage) Emulador de armazenamento Como um aplicativo de função no Azure requer uma conta de armazenamento, uma é atribuída ou criada quando você publica seu projeto no Azure. Um gatilho HTTP não usa uma cadeia de conexão de conta de Armazenamento do Azure; todos os outros tipos de gatilho exigem uma cadeia de conexão de conta de Armazenamento do Azure válida.
    Nível de autorização Anônimo A função criada pode ser acionada por qualquer cliente sem fornecer uma chave. Esta definição de autorização torna mais fácil testar a função nova. Para obter mais informações sobre chaves e autorização, consulte Chaves de autorização e Ligações HTTP e webhook.

    Screenshot of Azure Functions project settings

    Certifique-se de definir o nível de Autorização como Anônimo. Se você escolher o nível padrão de Função, será necessário apresentar a tecla de função em solicitações para acessar seu ponto de extremidade de função.

  5. Selecione Criar para criar o projeto de função e a função de gatilho HTTP.

Depois de criar um projeto do Azure Functions, o modelo de projeto cria um projeto C#, instala os Microsoft.Azure.Functions.Worker pacotes NuGet e Microsoft.Azure.Functions.Worker.Sdk define a estrutura de destino.

Depois de criar um projeto do Azure Functions, o modelo de projeto cria um projeto C#, instala o Microsoft.NET.Sdk.Functions pacote NuGet e define a estrutura de destino.

O novo projeto tem os seguintes arquivos:

  • host.json: Permite configurar o host Functions. Essas configurações se aplicam ao executar localmente e no Azure. Para obter mais informações, consulte host.json referência.

  • local.settings.json: Mantém as configurações usadas ao executar funções localmente. Essas configurações não são usadas durante a execução no Azure. Para obter mais informações, consulte Arquivo de configurações locais.

    Importante

    Como o arquivo local.settings.json pode conter segredos, você deve excluí-lo do controle do código-fonte do projeto. Verifique se a configuração Copiar para o diretório de saída para este arquivo está definida como Copiar se for mais recente.

Para obter mais informações, consulte Estrutura do projeto no Guia do trabalhador isolado.

Para obter mais informações, consulte Projeto de biblioteca de classes Functions.

Trabalhar com as configurações do aplicativo localmente

Quando executado em um aplicativo de função no Azure, as configurações exigidas por suas funções são armazenadas com segurança nas configurações do aplicativo. Durante o desenvolvimento local, essas configurações são adicionadas Values à coleção no arquivo local.settings.json. O arquivo local.settings.json também armazena as configurações usadas pelas ferramentas de desenvolvimento local.

Os itens na Values coleção no arquivo de local.settings.json do seu projeto destinam-se a espelhar itens nas configurações do aplicativo de função no Azure.

O Visual Studio não carrega automaticamente as configurações no local.settings.json quando você publica o projeto. Para certificar-se de que essas configurações também existem em seu aplicativo de função no Azure, carregue-as depois de publicar seu projeto. Para obter mais informações, consulte Configurações do aplicativo de função. Os valores de uma ConnectionStrings coleção nunca são publicados.

Seu código também pode ler os valores de configurações do aplicativo de função como variáveis de ambiente. Para obter mais informações, consulte Variáveis de ambiente.

Configurar o projeto para desenvolvimento local

O tempo de execução do Functions usa uma conta de Armazenamento do Azure internamente. Para todos os tipos de gatilho diferentes de HTTP e webhooks, defina a chave como uma cadeia de conexão de conta de Values.AzureWebJobsStorage Armazenamento do Azure válida. Seu aplicativo de função também pode usar o emulador Azurite para a configuração de AzureWebJobsStorage conexão exigida pelo projeto. Para usar o emulador, defina o valor de AzureWebJobsStorageUseDevelopmentStorage=truecomo . Altere essa configuração para uma cadeia de conexão de conta de armazenamento real antes da implantação. Para obter mais informações, consulte Emulador de armazenamento local.

Para definir a cadeia de conexão da conta de armazenamento:

  1. No portal do Azure, navegue para a sua conta de armazenamento.

  2. Na guia Teclas de acesso, abaixo de Segurança + rede, copie a Cadeia de conexão da chave1.

  3. Em seu projeto, abra o arquivo local.settings.json e defina o AzureWebJobsStorage valor da chave para a cadeia de conexão que você copiou.

  4. Repita a etapa anterior para adicionar chaves exclusivas à Values matriz para quaisquer outras conexões exigidas por suas funções.

Adicionar uma função ao seu projeto

Nas funções da biblioteca de classes C#, as associações usadas pela função são definidas pela aplicação de atributos no código. Quando você cria seus gatilhos de função a partir dos modelos fornecidos, os atributos de gatilho são aplicados para você.

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto e selecione Adicionar>Nova Função do Azure.

  2. Insira um Nome para a classe e selecione Adicionar.

  3. Escolha o gatilho, defina as propriedades de vinculação necessárias e selecione Adicionar. O exemplo a seguir mostra as configurações para criar uma função de gatilho de armazenamento de fila.

    Create a Queue storage trigger function

    Para um gatilho de serviço de Armazenamento do Azure, marque a caixa Configurar conexão e você será solicitado a escolher entre usar um emulador de armazenamento do Azurite ou fazer referência a uma conta de armazenamento do Azure provisionada. Selecione Avançar e, se você escolher uma conta de armazenamento, o Visual Studio tentará se conectar à sua conta do Azure e obter a cadeia de conexão. Escolha Salvar valor da cadeia de conexão no arquivo Segredos do usuário local e, em seguida, Concluir para criar a classe de gatilho.

    Este exemplo de gatilho usa uma configuração de aplicativo para a conexão de armazenamento com uma chave chamada QueueStorage. Essa chave, armazenada no arquivo local.settings.json, faz referência ao emulador do Azurite ou a uma conta de armazenamento do Azure.

  4. Examine a classe recém-adicionada. Por exemplo, a seguinte classe C# representa uma função básica de gatilho de armazenamento de fila:

    Você vê um método estático Run() atribuído com Function. Este atributo indica que o método é o ponto de entrada para a função.

    using System;
    using Azure.Storage.Queues.Models;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Logging;
    
    namespace Company.Function
    {
        public class QueueTriggerCSharp
        {
            private readonly ILogger<QueueTriggerCSharp> _logger;
    
            public QueueTriggerCSharp(ILogger<QueueTriggerCSharp> logger)
            {
                _logger = logger;
            }
    
            [Function(nameof(QueueTriggerCSharp))]
            public void Run([QueueTrigger("PathValue", Connection = "ConnectionValue")] QueueMessage message)
            {
                _logger.LogInformation($"C# Queue trigger function processed: {message.MessageText}");
            }
        }
    }
    

    Você vê um método estático Run() atribuído com FunctionName. Este atributo indica que o método é o ponto de entrada para a função.

    using System;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Logging;
    
    namespace Company.Function
    {
        public class QueueTriggerCSharp
        {
            [FunctionName("QueueTriggerCSharp")]
            public void Run([QueueTrigger("PathValue", Connection = "ConnectionValue")]string myQueueItem, ILogger log)
            {
                log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
            }
        }
    }
    

Um atributo específico de ligação é aplicado a cada parâmetro de ligação fornecido ao método de ponto de entrada. O atributo usa as informações de vinculação como parâmetros. No exemplo anterior, o primeiro parâmetro tem um QueueTrigger atributo aplicado, indicando uma função de gatilho de armazenamento de fila. O nome da fila e o nome da configuração da cadeia de conexão são passados como parâmetros para o QueueTrigger atributo. Para obter mais informações, consulte Associações de armazenamento de fila do Azure para o Azure Functions.

Use o procedimento acima para adicionar mais funções ao seu projeto de aplicativo de função. Cada função no projeto pode ter um gatilho diferente, mas uma função deve ter exatamente um gatilho. Para obter mais informações, veja Conceitos de acionadores e enlaces das Funções do Azure.

Adicionar enlaces

Assim como acontece com os gatilhos, as ligações de entrada e saída são adicionadas à sua função como atributos de ligação. Adicione associações a uma função da seguinte maneira:

  1. Certifique-se de configurar o projeto para desenvolvimento local.

  2. Adicione o pacote de extensão NuGet apropriado para a associação específica localizando os requisitos do pacote NuGet específicos da associação no artigo de referência para a associação. Por exemplo, localize os requisitos de pacote para o gatilho de Hubs de Eventos no artigo de referência de vinculação de Hubs de Eventos.

  3. Use o seguinte comando no Console do Gerenciador de Pacotes para instalar um pacote específico:

    Install-Package Microsoft.Azure.Functions.Worker.Extensions.<BINDING_TYPE> -Version <TARGET_VERSION>
    
    Install-Package Microsoft.Azure.WebJobs.Extensions.<BINDING_TYPE> -Version <TARGET_VERSION>
    

    Neste exemplo, substitua <BINDING_TYPE> pelo nome específico da extensão de vinculação e <TARGET_VERSION> por uma versão específica do pacote, como 4.0.0. As versões válidas estão listadas nas páginas de pacotes individuais em NuGet.org.

  4. Se houver configurações de aplicativo que a associação precisa, adicione-as Values à coleção no arquivo de configuração local.

    A função usa esses valores quando é executada localmente. Quando a função é executada no aplicativo de função no Azure, ela usa as configurações do aplicativo de função. O Visual Studio facilita a publicação de configurações locais no Azure.

  5. Adicione o atributo de vinculação apropriado à assinatura do método. No exemplo a seguir, uma mensagem de fila aciona a função e a associação de saída cria uma nova mensagem de fila com o mesmo texto em uma fila diferente.

     public class QueueTrigger
    {
        private readonly ILogger _logger;
    
        public QueueTrigger(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<QueueTrigger>();
        }
    
        [Function("CopyQueueMessage")]
        [QueueOutput("myqueue-items-destination", Connection = "QueueStorage")]
        public string Run([QueueTrigger("myqueue-items-source", Connection = "QueueStorage")] string myQueueItem)
        {
            _logger.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
            return myQueueItem;
        }
    }
    

    O QueueOutput atributo define a ligação no método. Para várias associações de saída, você colocaria esse atributo em uma propriedade string do objeto retornado. Para obter mais informações, consulte Várias ligações de saída.

    public static class SimpleExampleWithOutput
    {
        [FunctionName("CopyQueueMessage")]
        public static void Run(
            [QueueTrigger("myqueue-items-source", Connection = "QueueStorage")] string myQueueItem, 
            [Queue("myqueue-items-destination", Connection = "QueueStorage")] out string myQueueItemCopy,
            ILogger log)
        {
            log.LogInformation($"CopyQueueMessage function processed: {myQueueItem}");
            myQueueItemCopy = myQueueItem;
        }
    }
    

    O Queue atributo no parâmetro define a out ligação de saída.

    A conexão com o armazenamento em fila é obtida a QueueStorage partir da configuração. Para obter mais informações, consulte o artigo de referência para a vinculação específica.

Para obter uma lista completa das associações suportadas pelo Functions, consulte Ligações suportadas.

Executar funções localmente

As Ferramentas de Núcleo das Funções do Azure permitem-lhe executar o projeto de funções do Azure no seu computador de programação local. Quando você pressiona F5 para depurar um projeto do Functions, o host local do Functions (func.exe) começa a escutar em uma porta local (geralmente 7071). Todos os pontos de extremidade de função chamáveis são gravados na saída, e você pode usar esses pontos de extremidade para testar suas funções. Para obter mais informações, consulte Trabalhar com as ferramentas principais do Azure Functions. Você será solicitado a instalar essas ferramentas na primeira vez que iniciar uma função do Visual Studio.

Para iniciar sua função no Visual Studio no modo de depuração:

  1. Pressione F5. Se solicitado, aceite o pedido do Visual Studio para transferir e instalar as ferramentas de Núcleo das Funções do Azure (CLI). Também pode ser necessário habilitar uma exceção de firewall para que as ferramentas possam lidar com solicitações HTTP.

  2. Com o projeto em execução, teste seu código como você testaria uma função implantada.

    Quando você executa o Visual Studio no modo de depuração, os pontos de interrupção são atingidos conforme o esperado.

Para obter um cenário de teste mais detalhado usando o Visual Studio, consulte Testando funções.

Publicar no Azure

Quando você publica seu projeto de funções no Azure, o Visual Studio usa a implantação zip para implantar os arquivos de projeto. Quando possível, você também deve selecionar Run-From-Package para que o projeto seja executado no pacote de implantação (.zip). Para obter mais informações, consulte Executar suas funções a partir de um arquivo de pacote no Azure.

Não implante no Azure Functions usando a Implantação da Web (msdeploy).

Use as etapas a seguir para publicar seu projeto em um aplicativo de função no Azure.

  1. No Explorador de Soluções, clique com o botão direito do rato no projeto e selecione Publicar. Em Destino, selecione Azure e, em seguida, Avançar.

    Screenshot of publish window.

  2. Selecione Aplicativo de Função do Azure (Windows) para o destino Específico, que cria um aplicativo de função que é executado no Windows e, em seguida, selecione Avançar.

    Screenshot of publish window with specific target.

  3. Na Instância de Função, escolha Criar uma nova Função do Azure...

    Screenshot of create a new function app instance.

  4. Crie uma nova instância usando os valores especificados na tabela a seguir:

    Definição valor Descrição
    Nome Nome globalmente exclusivo Nome que identifica exclusivamente a sua nova aplicação de funções. Aceite este nome ou introduza um novo nome. Os caracteres válidos são: a-z, 0-9, e -.
    Subscrição a sua subscrição A subscrição do Azure que deve utilizar. Aceite esta subscrição ou selecione uma nova na lista pendente.
    Grupo de recursos Nome do grupo de recursos O grupo de recursos no qual você deseja criar seu aplicativo de função. Selecione Novo para criar um novo grupo de recursos. Você também pode escolher um grupo de recursos existente na lista suspensa.
    Tipo de Plano Consumo Quando você publica seu projeto em um aplicativo de função que é executado em um plano de consumo, você paga apenas pelas execuções do seu aplicativo de funções. Outros planos de hospedagem incorrem em custos mais altos.
    Location Localização do serviço da aplicação Escolha um local em uma região perto de você ou outros serviços que suas funções acessam.
    Armazenamento do Azure Conta de armazenamento de uso geral O runtime das Funções precisa de uma conta de armazenamento do Azure. Selecione Novo para configurar uma conta de armazenamento de uso geral. Você também pode escolher uma conta existente que atenda aos requisitos da conta de armazenamento.
    Application Insights Instância do Application Insights Você deve habilitar a integração do Application Insights para seu aplicativo de função. Selecione Novo para criar uma nova instância, em um espaço de trabalho novo ou existente do Log Analytics. Você também pode escolher uma instância existente.

    Screenshot of Create App Service dialog.

  5. Selecione Criar para criar um aplicativo de função e seus recursos relacionados no Azure. O status da criação de recursos é mostrado no canto inferior esquerdo da janela.

  6. Na instância Functions, verifique se a opção Executar do arquivo de pacote está marcada. Seu aplicativo de função é implantado usando o Zip Deploy com o modo Run-From-Package habilitado. Zip Deploy é o método de implantação recomendado para seu projeto de funções, resultando em melhor desempenho.

    Screenshot of Finish profile creation.

  7. Selecione Concluir e, na página Publicar, selecione Publicar para implantar o pacote que contém seus arquivos de projeto em seu novo aplicativo de função no Azure.

    Após a conclusão da implantação, a URL raiz do aplicativo de função no Azure é mostrada na guia Publicar .

  8. Na guia Publicar, na seção Hospedagem, escolha Abrir no portal do Azure. Isso abre o novo recurso do Azure do aplicativo de função no portal do Azure.

    Screenshot of Publish success message.

Definições da aplicação de funções

O Visual Studio não carrega essas configurações automaticamente quando você publica o projeto. Todas as configurações adicionadas no local.settings.json você também deve adicionar ao aplicativo de função no Azure.

A maneira mais fácil de carregar as configurações necessárias para seu aplicativo de função no Azure é expandir os três pontos ao lado da seção Hospedagem e selecionar o link Gerenciar configurações do Serviço de Aplicativo do Azure que aparece depois que você publica seu projeto com êxito.

Settings in Publish window

Selecionar este link exibe a caixa de diálogo Configurações do aplicativo para o aplicativo de função, onde você pode adicionar novas configurações do aplicativo ou modificar as existentes.

Application settings

Local exibe um valor de configuração no arquivo local.settings.json e Remote exibe um valor de configuração atual no aplicativo de função no Azure. Escolha Adicionar configuração para criar uma nova configuração de aplicativo. Use o link Inserir valor de Local para copiar um valor de configuração para o campo Remoto . As alterações pendentes são gravadas no arquivo de configurações local e no aplicativo de função quando você seleciona OK.

Nota

Por padrão, o arquivo local.settings.json não é verificado no controle do código-fonte. Isso significa que, se você clonar um projeto local do Functions a partir do controle do código-fonte, o projeto não terá um arquivo local.settings.json. Nesse caso, você precisa criar manualmente o arquivo local.settings.json na raiz do projeto para que a caixa de diálogo Configurações do aplicativo funcione conforme o esperado.

Você também pode gerenciar as configurações do aplicativo de uma destas outras maneiras:

Depuração Remota

Para depurar seu aplicativo de função remotamente, você deve publicar uma configuração de depuração do seu projeto. Você também precisa habilitar a depuração remota em seu aplicativo de função no Azure.

Esta seção pressupõe que você já tenha publicado em seu aplicativo de função usando uma configuração de versão.

Considerações sobre depuração remota

  • A depuração remota não é recomendada em um serviço de produção.
  • Se você tiver a depuração Just My Code ativada, desative-a.
  • Evite longas paradas em pontos de interrupção durante a depuração remota. O Azure trata um processo interrompido por mais do que alguns minutos como um processo sem resposta e o desliga.
  • Enquanto você está depurando, o servidor está enviando dados para o Visual Studio, o que pode afetar as cobranças de largura de banda. Para obter informações sobre taxas de largura de banda, consulte Preços do Azure.
  • A depuração remota é automaticamente desativada no seu aplicativo de função após 48 horas. Após 48 horas, você precisará reativar a depuração remota.

Anexar o depurador

A maneira como você anexa o depurador depende do seu modo de execução. Ao depurar um aplicativo de processo de trabalho isolado, você precisa anexar o depurador remoto a um processo .NET separado, e várias outras etapas de configuração são necessárias.

Quando terminar, desative a depuração remota.

Para anexar um depurador remoto a um aplicativo de função em execução em um processo separado do host Functions:

  1. Na guia Publicar, selecione as reticências (...) na seção Hospedagem e escolha Baixar perfil de publicação. Esta ação baixa uma cópia do perfil de publicação e abre o local de download. Você precisa desse arquivo, que contém as credenciais usadas para anexar ao seu processo de trabalho isolado em execução no Azure.

    Atenção

    O arquivo .publishsettings contém suas credenciais (não codificadas) que são usadas para administrar seu aplicativo de função. A prática recomendada de segurança para esse arquivo é armazená-lo temporariamente fora dos diretórios de origem (por exemplo, na pasta Bibliotecas\Documentos) e excluí-lo depois que não for mais necessário. Um usuário mal-intencionado que obtém acesso ao arquivo .publishsettings pode editar, criar e excluir seu aplicativo de função.

  2. Novamente na guia Publicar , selecione as reticências (...) na seção Hospedagem e escolha Anexar depurador.

    Screenshot of attaching the debugger from Visual Studio.

    O Visual Studio se conecta ao seu aplicativo de função e habilita a depuração remota, se ainda não estiver habilitada.

    Nota

    Como o depurador remoto não consegue se conectar ao processo do host, você pode ver um erro. Em qualquer caso, a depuração padrão não irá invadir seu código.

  3. De volta ao Visual Studio, copie a URL do Site em Hospedagem na página Publicar .

  4. No menu Depurar, selecione Anexar ao Processo e, na janela Anexar ao processo, cole a URL no Destino da Conexão, remova https:// e anexe a porta:4024.

    Verifique a aparência <FUNCTION_APP>.azurewebsites.net:4024 do seu destino e pressione Enter.

    Visual Studio attach to process dialog

  5. Se solicitado, permita o acesso ao Visual Studio por meio do firewall local.

  6. Quando as credenciais forem solicitadas, em vez de credenciais de usuário local, escolha uma conta diferente (Mais opções no Windows). Forneça os valores de userName e userPWD do perfil publicado para Endereço de email e Senha na caixa de diálogo de autenticação no Windows. Depois que uma conexão segura é estabelecida com o servidor de implantação, os processos disponíveis são mostrados.

    Visual Studio enter credential

  7. Marque Mostrar processo de todos os usuários e, em seguida, escolha dotnet.exe e selecione Anexar. Quando a operação for concluída, você será anexado ao código da biblioteca de classes C# em execução em um processo de trabalho isolado. Neste ponto, você pode depurar seu aplicativo de função normalmente.

Para anexar um depurador remoto a um aplicativo de função em execução no processo com o host Functions:

  • Na guia Publicar, selecione as reticências (...) na seção Hospedagem e escolha Anexar depurador.

    Screenshot of attaching the debugger from Visual Studio.

O Visual Studio se conecta ao seu aplicativo de função e habilita a depuração remota, se ainda não estiver habilitada. Ele também localiza e anexa o depurador ao processo de host do aplicativo. Neste ponto, você pode depurar seu aplicativo de função normalmente.

Desativar depuração remota

Depois de concluir a depuração remota do código, você deve desabilitar a depuração remota no portal do Azure. A depuração remota é automaticamente desativada após 48 horas, caso você se esqueça.

  1. Na guia Publicar em seu projeto, selecione as reticências (...) na seção Hospedagem e escolha Abrir no portal do Azure. Esta ação abre o aplicativo de função no portal do Azure no qual seu projeto está implantado.

  2. No aplicativo de funções, selecione Configuração em configurações, escolha Configurações Gerais, defina Depuração Remota como Desativado e selecione Salvar e Continuar.

Depois que o aplicativo de função for reiniciado, você não poderá mais se conectar remotamente aos seus processos remotos. Você pode usar essa mesma guia no portal do Azure para habilitar a depuração remota fora do Visual Studio.

Funções de monitorização

A maneira recomendada de monitorar a execução de suas funções é integrando seu aplicativo de função com o Azure Application Insights. Você deve habilitar essa integração ao criar seu aplicativo de função durante a publicação do Visual Studio.

Se, por algum motivo, a integração não tiver sido feita durante a publicação, você ainda deverá habilitar a integração do Application Insights para seu aplicativo de função no Azure.

Para saber mais sobre o monitoramento usando o Application Insights, consulte Monitorar o Azure Functions.

Testar funções

Esta seção descreve como criar um projeto de modelo em processo em C# que você pode testar com xUnit.

Testing Azure Functions with C# in Visual Studio

1. Configuração

Use estas etapas para configurar o ambiente, incluindo o projeto e as funções do aplicativo, necessários para dar suporte aos testes:

  1. Crie um novo aplicativo Functions e nomeie-o como Functions
  2. Crie uma função HTTP a partir do modelo e nomeie-a MyHttpTrigger.
  3. Crie uma função de temporizador a partir do modelo e nomeie-a MyTimerTrigger.
  4. Crie um aplicativo xUnit Test na solução e nomeie-o como Functions.Tests. Remova os arquivos de teste padrão.
  5. Use o NuGet para adicionar uma referência do aplicativo de teste a Microsoft.AspNetCore.Mvc
  6. Consulte o aplicativo Functions no aplicativo Functions.Tests.

Agora que os projetos são criados, você pode criar as classes usadas para executar os testes automatizados.

2. Criar classes de teste

Cada função usa uma instância de para lidar com o log de ILogger mensagens. Alguns testes não registram mensagens ou não têm nenhuma preocupação com a forma como o registro em log é implementado. Outros testes precisam avaliar as mensagens registradas para determinar se um teste está sendo aprovado.

  1. Crie uma classe chamada ListLogger, que contém uma lista interna de mensagens para avaliar durante o teste. Para implementar a interface necessária ILogger , a classe precisa de um escopo. A classe a seguir simula um escopo para os casos de teste passarem para a ListLogger classe.

  2. Crie uma nova classe em seu projeto Functions.Tests chamada NullScope.cs e adicione este código:

    using System;
    
    namespace Functions.Tests
    {
        public class NullScope : IDisposable
        {
            public static NullScope Instance { get; } = new NullScope();
    
            private NullScope() { }
    
            public void Dispose() { }
        }
    }
    
  3. Crie uma classe em seu projeto Functions.Tests chamada ListLogger.cs e adicione este código:

    using Microsoft.Extensions.Logging;
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Functions.Tests
    {
        public class ListLogger : ILogger
        {
            public IList<string> Logs;
    
            public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;
    
            public bool IsEnabled(LogLevel logLevel) => false;
    
            public ListLogger()
            {
                this.Logs = new List<string>();
            }
    
            public void Log<TState>(LogLevel logLevel,
                                    EventId eventId,
                                    TState state,
                                    Exception exception,
                                    Func<TState, Exception, string> formatter)
            {
                string message = formatter(state, exception);
                this.Logs.Add(message);
            }
        }
    }
    

    A ListLogger classe implementa os seguintes membros conforme contratado pela ILogger interface:

    • BeginScope: Os escopos adicionam contexto ao seu registro. Nesse caso, o teste apenas aponta para a instância estática na NullScope classe para permitir que o teste funcione.

    • IsEnabled: Um valor padrão de false é fornecido.

    • Log: Este método usa a função fornecida formatter para formatar a mensagem e, em seguida, adiciona o texto resultante à Logs coleção.

    A Logs coleção é uma instância de List<string> e é inicializada no construtor.

  4. Crie um arquivo de código no projeto Functions.Tests chamado LoggerTypes.cs e adicione este código:

    namespace Functions.Tests
    {
        public enum LoggerTypes
        {
            Null,
            List
        }
    }
    

    Esta enumeração especifica o tipo de logger usado pelos testes.

  5. Crie uma classe no projeto Functions.Tests chamada TestFactory.cs e adicione este código:

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.Internal;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Logging.Abstractions;
    using Microsoft.Extensions.Primitives;
    using System.Collections.Generic;
    
    namespace Functions.Tests
    {
        public class TestFactory
        {
            public static IEnumerable<object[]> Data()
            {
                return new List<object[]>
                {
                    new object[] { "name", "Bill" },
                    new object[] { "name", "Paul" },
                    new object[] { "name", "Steve" }
    
                };
            }
    
            private static Dictionary<string, StringValues> CreateDictionary(string key, string value)
            {
                var qs = new Dictionary<string, StringValues>
                {
                    { key, value }
                };
                return qs;
            }
    
            public static HttpRequest CreateHttpRequest(string queryStringKey, string queryStringValue)
            {
                var context = new DefaultHttpContext();
                var request = context.Request;
                request.Query = new QueryCollection(CreateDictionary(queryStringKey, queryStringValue));
                return request;
            }
    
            public static ILogger CreateLogger(LoggerTypes type = LoggerTypes.Null)
            {
                ILogger logger;
    
                if (type == LoggerTypes.List)
                {
                    logger = new ListLogger();
                }
                else
                {
                    logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
                }
    
                return logger;
            }
        }
    }
    

    A TestFactory classe implementa os seguintes membros:

    • Dados: Esta propriedade retorna uma coleção IEnumerable de dados de exemplo. Os pares de valores de chave representam valores que são passados para uma cadeia de caracteres de consulta.

    • CreateDictionary: Este método aceita um par chave/valor como argumentos e retorna um novo Dictionary usado para criar QueryCollection para representar valores de cadeia de caracteres de consulta.

    • CreateHttpRequest: Este método cria uma solicitação HTTP inicializada com os parâmetros de cadeia de caracteres de consulta fornecidos.

    • CreateLogger: Com base no tipo de logger, esse método retorna uma classe de logger usada para teste. O ListLogger mantém o controle de mensagens registradas disponíveis para avaliação em testes.

  6. Crie uma classe no projeto Functions.Tests chamada FunctionsTests.cs e adicione este código:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Logging;
    using Xunit;
    
    namespace Functions.Tests
    {
        public class FunctionsTests
        {
            private readonly ILogger logger = TestFactory.CreateLogger();
    
            [Fact]
            public async void Http_trigger_should_return_known_string()
            {
                var request = TestFactory.CreateHttpRequest("name", "Bill");
                var response = (OkObjectResult)await MyHttpTrigger.Run(request, logger);
                Assert.Equal("Hello, Bill. This HTTP triggered function executed successfully.", response.Value);
            }
    
            [Theory]
            [MemberData(nameof(TestFactory.Data), MemberType = typeof(TestFactory))]
            public async void Http_trigger_should_return_known_string_from_member_data(string queryStringKey, string queryStringValue)
            {
                var request = TestFactory.CreateHttpRequest(queryStringKey, queryStringValue);
                var response = (OkObjectResult)await MyHttpTrigger.Run(request, logger);
                Assert.Equal($"Hello, {queryStringValue}. This HTTP triggered function executed successfully.", response.Value);
            }
    
            [Fact]
            public void Timer_should_log_message()
            {
                var logger = (ListLogger)TestFactory.CreateLogger(LoggerTypes.List);
                new MyTimerTrigger().Run(null, logger);
                var msg = logger.Logs[0];
                Assert.Contains("C# Timer trigger function executed at", msg);
            }
        }
    }
    

    Os membros implementados nesta classe são:

    • Http_trigger_should_return_known_string: Este teste cria uma solicitação com os valores da cadeia de caracteres de consulta de name=Bill para uma função HTTP e verifica se a resposta esperada é retornada.

    • Http_trigger_should_return_string_from_member_data: Este teste usa atributos xUnit para fornecer dados de exemplo para a função HTTP.

    • Timer_should_log_message: Este teste cria uma instância e passa-a para uma função de ListLogger temporizador. Uma vez que a função é executada, em seguida, o log é verificado para certificar-se de que a mensagem esperada está presente.

  7. Para acessar as configurações do aplicativo em seus testes, você pode injetar uma IConfiguration instância com valores de variáveis de ambiente simulados em sua função.

3. Executar testes

Para executar os testes, navegue até o Gerenciador de Testes e selecione Executar Todos os Testes em Exibição.

Testing Azure Functions with C# in Visual Studio

4. Testes de depuração

Para depurar os testes, defina um ponto de interrupção em um teste, navegue até o Gerenciador de Testes e selecione Executar > Última Execução de Depuração.

Próximos passos

Para obter mais informações sobre as Ferramentas Principais do Azure Functions, consulte Trabalhar com as Ferramentas Principais do Azure Functions.