Criar e testar uma Função do Azure simples localmente com o Visual Studio

Concluído

Os usuários podem escrever, depurar e implantar uma Função do Azure no portal do Azure. No entanto, pode ser que a gravação de funções diretamente em um ambiente de produção, de preparo ou de teste não seja adequada. Por exemplo, a escrita de testes de unidade automatizados para o Azure Functions ou o uso da implantação sob demanda do Azure Functions para os Aplicativos de Funções no Azure. De modo geral, os desenvolvedores preferem usar um editor de código e ferramentas de desenvolvimento favoritos em vez do ambiente fornecido pelo portal do Azure. O Visual Studio permite desenvolver e gerenciar o Azure Functions código usando outros códigos e serviços em um projeto único.

No cenário de relógios de luxo online, os desenvolvedores já estão familiarizados com o Visual Studio 2022. Portanto, você decide usar o Visual Studio como o ambiente de desenvolvimento principal para a criação de Azure Functions. Além disso, o Visual Studio fornece um ambiente excelente para testar suas funções localmente antes de implantá-las no Azure.

Nesta unidade, você vai aprender a usar as ferramentas disponíveis no Visual Studio para criar e testar uma função do Azure no computador local.

Importante

Este artigo serve para funções de biblioteca de classes do .NET, que são executadas em processo com o runtime. Suas funções C# também podem ficar fora do processo e isoladas do runtime do Functions. O modelo de processo de trabalho isolado é a única maneira de executar versões não LTS dos aplicativos .NET e .NET Framework nas versões atuais do runtime do Functions. Para saber mais, confira funções de processo de trabalho isolado no .NET.

Modificar a instalação do Visual Studio

Primeiro, vamos configurar o Visual Studio com as ferramentas da web e de nuvem necessárias para o ambiente de desenvolvimento.

  1. Com o Visual Studio 2022 instalado localmente, abra o Instalador do Visual Studio e, no Visual Studio Community 2022, selecione Modificar.

    Captura de tela do Instalador do Visual Studio com Modificar realçado.

  2. A página Modificando – Visual Studio é exibida.

    Captura de tela da guia Modificando as cargas de trabalho do Visual Studio Community 2022 com ASP.NET e desenvolvimento para a Web e desenvolvimento do Azure realçado.

  3. Na guia Cargas de Trabalho, selecione as caixas ASP.NET e Desenvolvimento para a Web e Desenvolvimento do Azure e, em seguida, selecione Modificar.

  4. Na caixa de diálogo de verificação, selecione Sim. A página Instalador do Visual Studio é exibida e exibe o progresso dos pacotes que estão sendo instalados.

Extensão Azure Functions Tools para Visual Studio

O Azure Functions Tools é uma extensão do Visual Studio que permite a criação, o teste e a implantação de funções do Azure em seu ambiente de desenvolvimento local. Para criar rapidamente um novo Aplicativo de Funções do Azure, essa extensão fornece um modelo para você criar e, em seguida, implantar uma função diretamente no Azure por meio do Visual Studio.

A extensão Azure Functions and Web Jobs Tools está incluída no Visual Studio 2022.

Aplicativo de Funções do Azure

Um aplicativo de funções hospeda uma ou mais funções. Ele fornece o ambiente e o runtime para o seu código de função.

Uma função é disparada por um evento em vez de ser chamada diretamente de um aplicativo. Especifique o tipo de evento que vai disparar cada função no Aplicativo de Funções do Azure. Os eventos disponíveis incluem:

  • Gatilho de blob. Esse tipo de função é executado quando um arquivo é carregado ou modificado no Armazenamento de Blobs do Azure.
  • Gatilho do Hub de Eventos. Um gatilho dos Hubs de Eventos executa a função quando um hub de eventos recebe uma mensagem.
  • Gatilho do Azure Cosmos DB. Esse gatilho é executado quando um documento é adicionado a um banco de dados do Azure Cosmos DB ou modificado nele. Use esse gatilho para integrar o Azure Cosmos DB a outros serviços. Por exemplo, se um documento que representa o pedido de um cliente é adicionado a um banco de dados, você pode usar um gatilho para enviar uma cópia do pedido a uma fila para processamento.
  • Gatilho HTTP. Um gatilho HTTP executa a função quando uma solicitação HTTP ocorre em um aplicativo Web. Use também esse gatilho para responder a webhooks. Um webhook é um retorno de chamada que ocorre quando um item hospedado por um site é modificado. Por exemplo, você pode criar uma função acionada por um webhook de um repositório do GitHub quando um item no repositório é alterado.
  • Gatilho de Fila. Esse gatilho inicia a função quando um novo item é adicionado a uma fila do Armazenamento do Azure.
  • Gatilho de Fila do Barramento de Serviço. O gatilho executa a função quando um novo item é adicionado a uma fila do Barramento de Serviço do Azure.
  • Gatilho de Tópico do Barramento de Serviço. Esse gatilho executa a função em resposta a uma nova mensagem recebida em um tópico do Barramento de Serviço.
  • Gatilho de Temporizador. Esse evento executa a função em intervalos regulares, seguindo um agendamento definido.

Captura de tela mostrando os gatilhos do Azure Functions disponíveis, com o gatilho HTTP realçado.

A tabela a seguir mostra o nível mais alto do .NET Core ou .NET Framework que pode ser usado com uma versão específica do Functions.

Versão do runtime do Functions Em processo Processo de trabalho isolado
Functions 4.x .NET 6.0 .NET 6.0
.NET 7.0
.NET 8.0
.NET Framework 4.8
Funções 1.x .NET Framework 4.8 n/d

Um Aplicativo de Funções do Azure armazena informações de gerenciamento, de código e de logs no armazenamento do Azure. Para guardar esses dados, você cria uma Conta de Armazenamento. A conta de armazenamento precisa dar suporte ao Armazenamento de Blobs, Fila, Arquivos e Tabela do Azure; use uma conta geral do Armazenamento do Azure para essa finalidade. Especifique qual conta de armazenamento será usada para a função usando a caixa de diálogo mostrada anteriormente.

Uma função pode executar operações privilegiadas ou confidenciais. Uma função disparada por uma solicitação HTTP pode ser exposta publicamente. Talvez você precise limitar a capacidade de executar essa função aos grupos de usuários selecionados. Proteja uma função especificando os direitos de acesso necessários para disparar a função. Uma função disparada por uma solicitação HTTP dá suporte a três níveis de direitos de acesso:

  • Anônimo. Nenhuma autenticação é necessária, e qualquer usuário pode disparar a função.
  • Função. A solicitação HTTP precisa fornecer uma chave que permite que o Azure Functions Runtime autorize a solicitação. Você cria essa chave separadamente e a mantém usando o portal do Azure.
  • Admin. Isso é semelhante à Função. O usuário precisa especificar uma chave com a solicitação HTTP que dispara a função. A diferença é que a chave é uma chave de administrador. Essa chave pode ser usada para acessar qualquer função no aplicativo de funções. Assim como acontece com uma chave de função, você cria essa chave separadamente.

Se você estiver criando uma função disparada por eventos que não sejam solicitações HTTP, precisará fornecer uma cadeia de conexão e outros detalhes necessários para o aplicativo de funções acessar o recurso que dispara o evento. Por exemplo, se você estiver escrevendo uma função disparada por um evento do Armazenamento de Blobs, precisará especificar a cadeia de conexão para a conta do Armazenamento de Blobs correspondente.

Estrutura de uma Função do Azure

Uma Função do Azure é implementada como uma classe estática. A classe fornece um método estático e assíncrono chamado Run, que funciona como o ponto de entrada para a classe.

Os parâmetros passados para o método Run fornecem o contexto para o gatilho. Se for um gatilho HTTP, a função recebe um objeto HttpRequest. Esse objeto contém o cabeçalho e o corpo da solicitação. Você pode acessar os dados na solicitação usando as mesmas técnicas disponíveis em qualquer aplicativo HTTP. Os atributos aplicados a essa função especificam os requisitos de autorização (Anônimo, nesse caso) e as operações HTTP para as quais a função responde (GET e POST).

O código de exemplo a seguir, gerado pelo Visual Studio, examina a cadeia de consulta fornecida como parte da URL para a solicitação e procura um parâmetro chamado nome. O código também usa um StreamReader para desserializar o corpo da solicitação e tenta ler o valor de uma propriedade também chamada nome da solicitação. Se o nome estiver presente na cadeia de caracteres de consulta ou no corpo da solicitação, o valor do nome será retornado na resposta. Caso contrário, a função gerará uma resposta de erro com a mensagem: Passe um nome na cadeia de caracteres de consulta ou no corpo da solicitação.

public static class Function1
{
    [FunctionName("Function1")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        string name = req.Query["name"];

        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
        name = name ?? data?.name;

        return name != null
            ? (ActionResult)new OkObjectResult($"Hello, {name}")
            : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
    }
}

A função retorna um valor contendo dados de saída e resultados, encapsulados em um objeto IActionResult. O valor é retornado no corpo da resposta HTTP para a solicitação.

Diferentes tipos de gatilhos recebem diferentes parâmetros de entrada e tipos de retorno. O próximo exemplo mostra o código gerado para um gatilho de Blob. Nesse exemplo, o conteúdo do blob é retornado por meio de um objeto Stream, e o nome do blob também é fornecido. O gatilho não retorna nenhum dado; sua finalidade é ler e processar os dados no blob nomeado.

public static class Function2
{
    [FunctionName("Function2")]
    public static void Run([BlobTrigger("samples-workitems/{name}", Connection = "xxxxxxxxxxxxxxxxxxxxxxx")]Stream myBlob, string name, ILogger log)
    {
        log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
    }
}

Em todos os casos, uma função recebe um parâmetro ILogger. A função pode usar esse parâmetro para gravar mensagens de log, que o aplicativo de função grava no armazenamento para analisar depois.

Uma função também contém metadados que especificam o tipo do gatilho, os requisitos de segurança, bem como outras informações específicas de segurança. Modifique os metadados usando o HttpTrigger, BlobTrigger ou outros atributos de gatilho, conforme mostrado nos exemplos. O atributo FunctionName que precede uma função é um identificador para a função usada pelo Aplicativo de Funções. Esse nome não precisa ser igual ao nome da função, mas é uma boa prática mantê-los sincronizados para evitar confusão.

Testar um Aplicativo de funções do Azure localmente

Use o Depurador Visual para criar e testar o Aplicativo de Funções do Azure localmente. Para inicializar o depurador, pressione F5 ou, no menu Depurar, selecione Iniciar Depuração. A versão local do Runtime de Função é iniciada. As funções estão prontas para serem testadas. O exemplo mostra o runtime que hospeda Function1, a função disparada por um evento HTTP. A URL indica o ponto de extremidade ao qual a função está anexada no momento.

Captura de tela mostrando o Azure Functions Runtime – exemplo 1.

Se você abrir um navegador e visitar essa URL, a função dispara. A imagem a seguir mostra a resposta gerada por uma solicitação HTTP GET que não inclui um corpo. Você pode ver a mensagem gerada pelo código que retorna o objeto BadRequestObjectResult da função.

Captura de tela mostrando o Azure Functions Runtime.

Se você fornecer uma cadeia de consulta que inclui um parâmetro name, a função irá ler e processar esse valor.

Captura de tela mostrando o Azure Functions Runtime – exemplo 2.

Durante a execução do código, você observa mensagens de rastreamento exibidas na janela do Runtime de Função. Você pode usar as funcionalidades de depuração padrão no Visual Studio caso precise definir pontos de interrupção e examinar o fluxo de controle em uma função.