Desenvolver o Azure Functions usando o Visual Studio

O Visual Studio permite que você desenvolva, teste e implante funções da biblioteca de classes C# no Azure. Se esta for sua primeira experiência com o Azure Functions, confira Uma introdução ao Azure Functions.

Para começar imediatamente, considere concluir o início rápido do Functions para o 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 as funções da biblioteca de classes em C#: o modelo de trabalho isolado e o modelo em processo.

Você está lendo a versão isolada do modelo de trabalho neste artigo. Você pode escolher seu modelo preferencial na parte superior do artigo.

Você está lendo a versão do modelo em processo neste artigo. Você pode escolher seu modelo preferencial na parte superior do artigo.

Os procedimentos e exemplos mostrados são para o Visual Studio 2022, a não ser que haja alguma indicação contrária. Para obter mais informações sobre as versões do Visual Studio 2022, confira as notas sobre a versão ou as notas sobre a versão prévia.

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.

  • Caso você não tenha uma assinatura do Azure, crie uma conta gratuita do Azure antes de começar.

Criar um projeto do Azure Functions

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ções no Azure. Você pode usar um aplicativo de funções 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 do Visual Studio, selecione Arquivo>Novo>Projeto.

  2. Em Criar um projeto, insira funções na caixa de pesquisa, escolha o modelo Azure Functions e, em seguida, selecione Próximo.

  3. Em Configurar seu novo projeto, insira um Nome de projeto para seu projeto e, em seguida, selecione Criar. O nome do aplicativo de funções deve ser válido como um namespace do C# e, portanto, não use outros caracteres não alfanuméricos, hífens ou sublinhados.

  4. Para as configurações de Criar um aplicativo do Azure Functions, use os valores da tabela a seguir:

    Configuração Valor Descrição
    Versão do .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 dá suporte a outra versão não LTS do .NET e também ao .NET Framework. Para obter mais informações, consulte Visão geral de versões do Azure Functions runtime.
    Modelo de função Gatilho 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ções no Azure requer uma conta de armazenamento, ela será atribuída ou criada quando você publicar seu projeto no Azure. Um gatilho HTTP não usa uma cadeia de conexão da conta do Armazenamento do Azure; todos os outros tipos de gatilho exigem uma cadeia de conexão válida da conta do Armazenamento do Azure.
    Nível de autorização Anônimo A função criada pode ser acionada por qualquer cliente sem fornecer uma chave. Essa configuração de autorização torna fácil testar a nova função. Para obter mais informações sobre chaves e autorização, consulte Chaves de autorização e associações HTTP e webhook.

    Screenshot of Azure Functions project settings

    Configuração Valor Descrição
    Versão do .NET .NET 6 Esse valor cria um projeto de função que é executado em processo com a versão 4.x do Azure Functions Runtime. Para obter mais informações, consulte Visão geral de versões do Azure Functions runtime.
    Modelo de função Gatilho 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ções no Azure requer uma conta de armazenamento, ela será atribuída ou criada quando você publicar seu projeto no Azure. Um gatilho HTTP não usa uma cadeia de conexão da conta do Armazenamento do Azure; todos os outros tipos de gatilho exigem uma cadeia de conexão válida da conta do Armazenamento do Azure.
    Nível de autorização Anônimo A função criada pode ser acionada por qualquer cliente sem fornecer uma chave. Essa configuração de autorização torna fácil testar a nova função. Para obter mais informações sobre chaves e autorização, consulte Chaves de autorização e associações HTTP e webhook.

    Screenshot of Azure Functions project settings

    Verifique se você definiu o Nível de autorização como Anônimo. Se você escolher o nível padrão da Função, será necessário que você apresente a chave da função em solicitações para acessar seu ponto de extremidade da 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 em C#, instala os pacotes NuGet Microsoft.Azure.Functions.Worker e Microsoft.Azure.Functions.Worker.Sdk, e define a estrutura de destino.

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

O novo projeto contém os seguintes arquivos:

  • host.json: Permite que você configure o host do Functions. Essas configurações se aplicam para execução local e no Azure. Para obter mais informações, consulte a referência para host.json.

  • local.Settings.json: Mantém as configurações usadas ao executar as funções localmente. Essas configurações não são usadas quando estão em execução no Azure. Para obter mais informações, confira Arquivo de configurações local.

    Importante

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

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

Trabalhe com as configurações do aplicativo localmente

Ao executar em um aplicativo de funções 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 à coleção Values no arquivo local.settings.json. O arquivo local.settings.json também armazena as configurações usadas pelas ferramentas de desenvolvimento locais.

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

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

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

Configurar seu projeto para desenvolvimento local

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

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

  1. No portal do Azure, navegue até sua conta de armazenamento.

  2. Na guia Chaves de acesso, abaixo de Segurança + rede, copie a Cadeia de conexão de key1.

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

  4. Repita a etapa anterior para adicionar as chaves exclusivas para a matriz de Values para todas as outras conexões necessárias para as suas funções.

Adicionar uma função ao projeto

Nas funções da biblioteca de classes C#, as associações usadas pela função são definidas aplicando atributos no código. Quando você cria seus gatilhos de função com base nos 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 seu projeto e selecione Adicionar>Novo Azure Function.

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

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

    Create a Queue storage trigger function

    Quanto a um gatilho de serviço de Armazenamento do Azure, marque a caixa Configurar conexão e você deverá escolher entre usar um emulador de armazenamento do Azurite ou referenciar uma conta de armazenamento provisionada do Azure. Selecione Próximo 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 o valor da cadeia de conexão no arquivo de segredos do Usuário local e Concluir para criar a classe de gatilho.

    Esse 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 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 filas:

    Você vê um método Run() estático atribuído com Function. Esse 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 Run() estático atribuído com FunctionName. Esse 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 associação é aplicado a cada parâmetro de associação fornecido ao método do ponto de entrada. O atributo utiliza as informações de associação como parâmetros. No exemplo anterior, o primeiro parâmetro tem um atributo QueueTrigger aplicado, que indica a função de gatilho de armazenamento de filas. O nome da fila e o nome de configuração da cadeia de conexão são passadas como parâmetros ao atributo QueueTrigger. Para obter mais informações, veja Associações do armazenamento de Fila do Azure para o Azure Functions.

Use o procedimento acima para adicionar mais funções a seu projeto de aplicativo de funções. Cada função no projeto pode ter um gatilho diferente, mas uma função deve ter apenas um gatilho. Para obter mais informações, consulte Gatilhos e conceitos de associações do Azure Functions.

Adicionar associações

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

  1. Verifique se você configurou o projeto de desenvolvimento local.

  2. Adicione o pacote de extensão NuGet apropriado para a associação específica encontrando os requisitos de pacote NuGet específicos da associação no artigo de referência para a associação. Por exemplo, encontre os requisitos do pacote para o gatilho dos Hubs de Eventos no artigo de referência da associação dos 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 ligação e <TARGET_VERSION> por uma versão específica do pacote, tal como 4.0.0. Versões válidas são listadas nas páginas de pacotes individuais em NuGet.org.

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

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

  5. Adicione o atributo de associação apropriado para a assinatura do método. No exemplo a seguir, uma mensagem da fila dispara 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 atributo QueueOutput define a associação no método. Quanto às várias associações de saída, coloque esse atributo em uma propriedade de cadeia de caracteres do objeto retornado. Para obter mais informações, consulte Várias associaçõ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 atributo Queue no parâmetro out define a associação de saída.

    A conexão com o Armazenamento de filas é obtida na configuração QueueStorage. Para saber mais, confira o artigo de referência da associação específica.

Para ver uma lista completa das vinculações compatíveis com o Functions, confira Vinculações compatíveis.

Executar funções localmente

As Ferramentas Principais do Azure Functions permitem executar o projeto do Azure Functions no seu computador de desenvolvimento local. Quando você pressiona F5 para depurar um projeto do Functions, o host local do Functions (func.exe) começa a escutar uma porta local (geralmente, a 7071). Todos os pontos de extremidade de função que podem ser chamados são gravados na saída, e você pode usar esses pontos de extremidade para testar as funções. Para obter mais informações, confira Trabalhar com o Azure Functions Core Tools. É solicitado que você instale essas ferramentas na primeira vez em que inicia uma função no Visual Studio.

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

  1. Pressione F5. Se solicitado, aceite a solicitação do Visual Studio para baixar e instalar as ferramentas principais (CLI) do Azure Functions. Além disso, talvez seja necessário habilitar uma exceção de firewall para que as ferramentas possam manipular solicitações HTTP.

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

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

Para ver um cenário de teste mais detalhado usando o Visual Studio, confira Funções de teste.

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 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 para um aplicativo de funções no Azure.

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no nome do projeto e selecione Publicar. Em Destino, selecione Azure e Avançar.

    Screenshot of publish window.

  2. Escolha Aplicativo de Funções do Azure (Windows) em Destino específico, o que criará um aplicativo de funções executado no Windows, e selecione Avançar.

    Screenshot of publish window with specific target.

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

    Screenshot of create a new function app instance.

  4. Crie uma instância usando os valores especificados nesta tabela:

    Configuração Valor Descrição
    Nome Nome globalmente exclusivo Nome que identifica seu novo aplicativo de funções de forma exclusiva. Aceite esse nome ou insira um novo nome. Os caracteres válidos são: a-z, 0-9 e -.
    Assinatura Sua assinatura A assinatura do Azure a utilizar. Aceite esta assinatura ou selecione uma nova na lista suspensa.
    Grupo de recursos Nome do seu grupo de recursos O grupo de recursos no qual você deseja criar o aplicativo de funções. 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ções 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.
    Localidade Local do serviço de aplicativo Escolha um Local em uma região perto de você ou de outros serviços acessados pelas suas funções.
    Armazenamento do Azure Conta de armazenamento para uso geral Uma conta de armazenamento do Azure é requerida pelo runtime do Functions. Selecione Novo para configurar uma conta de armazenamento para 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ções. Selecione Novo para criar uma nova instância, em um workspace novo ou em um workspace do Log Analytics existente. Você também pode escolher uma instância existente.

    Screenshot of Create App Service dialog.

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

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

    Screenshot of Finish profile creation.

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

    Concluída a implantação, a URL raiz do aplicativo de funções no Azure é mostrada na guia Publicar.

  8. Na guia Publicar, na seção Hospedagem, escolha Abrir no portal do Azure. O novo recurso de aplicativo de funções do Azure é aberto no portal do Azure.

    Screenshot of Publish success message.

Configurações do aplicativo de funções

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

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

Settings in Publish window

Selecionar esse link exibe a caixa de diálogo Configurações de 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 Remoto exibe uma configuração atual no aplicativo de funções no Azure. Escolha Adicionar configuração para criar uma nova configuração de aplicativo. Use o link Inserir valor do local para copiar um valor de configuração para o campo Remoto. As alterações pendentes serão gravadas no arquivo de configurações local e no aplicativo de funções quando você selecionar OK.

Observação

Por padrão, o check-in do arquivo local.settings.json não é feito no controle do código-fonte. Isso significa que, se você clonar um projeto local do Functions do controle do código-fonte, o projeto não terá um arquivo local.settings.json. Nesse caso, você precisa criar manualmente o local.settings.json arquivo 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 de aplicativo em um desses outros modos:

Depuração remota

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

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

Considerações de depuração remota

  • A depuração remota não é recomendada em um serviço de produção.
  • Se você tiver a depuração Apenas Meu Código habilitada, desabilite-a.
  • Evite paradas longas em pontos de interrupção durante a depuração remota. O Azure trata um processo parado por mais de 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 os encargos de largura de banda. Para obter informações sobre as taxas de largura de banda, consulte Preço do Azure.
  • A depuração remota é desabilitada automaticamente em seu aplicativo de funções após 48 horas. Após 48 horas, você precisará reabilitar a depuração remota.

Anexar o depurador

A maneira como você anexa o depurador depende do 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, você deve desabilitar a depuração remota.

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

  1. Na guia Publicar, selecione as reticências (...) na seção Hosting e escolha Baixar perfil de publicação. Essa 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 a serem anexadas ao processo de trabalho isolado em execução no Azure.

    Cuidado

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

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

    Screenshot of attaching the debugger from Visual Studio.

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

    Observação

    Como o depurador remoto não é capaz de se conectar ao processo de host, você pode ver um erro. De qualquer forma, a depuração padrão não será dividida em seu código.

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

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

    Verifique se o destino tem aparência <FUNCTION_APP>.azurewebsites.net:4024 e pressione Enter.

    Visual Studio attach to process dialog

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

  6. Quando solicitado a inserir credenciais, 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 no perfil de publicação de 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 processos de todos os usuários, 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ções normalmente.

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

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

    Screenshot of attaching the debugger from Visual Studio.

O Visual Studio se conecta ao aplicativo de funções 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ções normalmente.

Desabilitar 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 é desabilitada automaticamente após 48 horas, caso você esqueça.

  1. Na guia Publicar em seu projeto, selecione as reticências (...) na seção Hosting e escolha Abrir no portal do Azure. Essa ação abre o aplicativo de funções no portal do Azure no qual seu projeto é 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ções 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 monitoramento

A maneira recomendada de monitorar a execução de suas funções é a integração do aplicativo de funções com o Azure Application Insights. Você deve habilitar essa integração ao criar seu aplicativo de funções 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 no seu aplicativo de funções no Azure.

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

Funções de teste

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. Instalaçã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 aplicativo de funções e nomeie-o como Functions
  2. Crie uma função HTTP a partir do modelo e nomeie-a MyHttpTrigger.
  3. Crie uma função temporizadora do modelo e nomeie-a MyTimerTrigger.
  4. Crie um aplicativo de teste xUnit na solução e nomeie-o como functions. Tests. Remova os arquivos de teste padrão.
  5. Use NuGet para adicionar uma referência do aplicativo para teste para Microsoft.AspNetCore.Mvc
  6. Referencie o aplicativo Functions no aplicativo Functions.Test.

Agora que os projetos foram criados, será possível criar as classes usadas para executar os testes automatizados.

2. Criar classes de teste

Cada função usa uma instância de ILogger para lidar com o registro em log de mensagens. Alguns testes não registram mensagens ou não se preocupam com como log é implementado. Outros testes precisam avaliar as mensagens registradas para determinar se foram aprovadas.

  1. Crie uma classe chamada ListLogger, que contenha uma lista interna das mensagens a serem avaliadas durante o teste. Para implementar a interface ILogger necessária, a classe precisa de um escopo. A classe a seguir simula um escopo para os casos de teste passar para a classe ListLogger.

  2. Crie uma nova classe no 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 no 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 classe ListLogger implementará os seguintes membros, conforme contratado pela interface ILogger:

    • BeginScope: define o escopo de adicionar contexto do log. Nesse caso, o teste somente aponta para a instância estática na classe NullScope para permitir que o teste funcione.

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

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

    A coleção Logs é 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 agente 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 classe TestFactory implementa os seguintes membros:

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

    • CreateDictionary: esse 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: esse método cria uma solicitação HTTP inicializada com os parâmetros de cadeia de caracteres de consulta fornecidos.

    • CreateHttpRequest: com base no tipo de agente, esse método retornará uma classe de agente usada para teste. O ListLogger controla as 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: esse 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 será retornada.

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

    • Timer_should_log_message: esse teste cria uma instância de ListLogger e a envia a uma função de temporizador. Depois que a função é executada, o log é verificado para garantir que a mensagem esperada esteja presente.

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

3. Executar testes

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

Testing Azure Functions with C# in Visual Studio

4. Depurar testes

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

Próximas etapas

Para obter mais informações sobre o Azure Functions Core Tools, confira Trabalhar com o Azure Functions Core Tools.