Share via


Tutorial: Introdução ao Azure Functions e Visual Studio para Mac

Importante

O Visual Studio para Mac está programado para ser desativado em 31 de agosto de 2024, de acordo com a Política de Ciclo de Vida Moderna da Microsoft. Embora você possa continuar a trabalhar com o Visual Studio para Mac, há várias outras opções para desenvolvedores no Mac, como a versão prévia da nova extensão do Kit de Desenvolvimento em C# para VS Code.

Saiba mais sobre cronogramas e alternativas de suporte.

Neste laboratório, você aprenderá a começar a criar no Azure Functions usando o Visual Studio para Mac. Você também fará a integração com as tabelas do Armazenamento do Azure, que representam um dos muitos tipos de associações e gatilhos disponíveis para os desenvolvedores no Azure Functions.

Objetivos

  • Criar e depurar funções do Azure locais
  • Integrar com recursos do Armazenamento do Azure e da Web
  • Organizar um fluxo de trabalho envolvendo várias funções do Azure

Requisitos

  • Visual Studio para Mac 7.5 ou posterior.
  • Uma assinatura do Azure (disponível gratuitamente em https://azure.com/free).

Exercício 1: Criar um projeto do Azure Functions

  1. Inicialize o Visual Studio para Mac.

  2. Selecione Arquivo > Nova Solução.

  3. Na categoria Nuvem > Geral, selecione o modelo Azure Functions. Você usará o C# para criar uma biblioteca de classes .NET que hospeda o Azure Functions. Clique em Próximo.

    Azure Functions template selection

  4. Definir o Nome do Projeto como "AzureFunctionsLab" e clique em Criar.

    naming and creating your Azure function project

  5. Expanda os nós na Janela da Solução. O modelo de projeto padrão inclui referências de NuGet a uma variedade de pacotes do Azure WebJobs, bem como ao pacote Newtonsoft.Json.

    Também há três arquivos: - host.json para descrever as opções de configuração globais para o host - local.settings.json para definir as configurações de serviço. - O modelo de projeto também cria um HttpTrigger padrão. Para este laboratório, você deve excluir o arquivo HttpTrigger.cs do projeto.

    Abra local.settings.json. O padrão é ter duas configurações de cadeia de conexão vazias.

    solution window displaying local.settings.json file

Exercício 2: Criar uma conta do Armazenamento do Azure

  1. Faça logon na sua conta do Azure em https://portal.azure.com.

  2. Na seção Favoritos, localizada à esquerda na tela, selecione Contas de Armazenamento:

    favorites section of Azure portal showing storage accounts item

  3. Selecione Adicionar para criar uma nova conta de armazenamento:

    Button to add new storage account

  4. Insira um nome global exclusivo em Nome e reutilize-o para o Grupo de recursos. Você pode manter todos os outros itens com os valores padrão.

    new storage account details

  5. Clique em Criar. Pode levar alguns minutos para criar a conta de armazenamento. Você receberá uma notificação quando ela tiver sido criada com êxito.

    deployment successful notification

  6. Selecione o botão Ir para o recurso na notificação.

  7. Selecione a guia Chaves de acesso.

    access key setting

  8. Copie a primeira Cadeia de conexão. Essa cadeia de caracteres é usada para integrar o Armazenamento do Azure com o Azure Functions posteriormente.

    information for key 1

  9. Retorne ao Visual Studio para Mac e cole a cadeia de conexão completa como a configuração AzureWebJobsStorage em local.settings.json. Agora, você pode referenciar o nome da configuração nos atributos para funções que precisam de acesso a seus recursos.

    local settings file with connection key entered

Exemplo 3: Criar e depurar uma função do Azure

  1. Agora, você está pronto para começar a adicionar algum código. Ao trabalhar com uma biblioteca de classes .NET, funções do Azure são adicionadas como métodos estáticos. Na Janela da Solução, clique com o botão direito do mouse no nó do projeto AzureFunctions e selecione Adicionar > Adicionar Função:

    Add function option

  2. Na caixa de diálogo Novas Funções do Azure, selecione o modelo de webhook Genérico. Definir o Nome a Adicionar e clique em OK para criar a função:

    New Azure Functions dialog

  3. Na parte superior do novo arquivo, adicione as diretivas using abaixo:

    using Microsoft.Azure.WebJobs.Extensions.Http;
    using System.Web;
    using Microsoft.WindowsAzure.Storage.Table;
    
  4. Remova o método Run existente e adicione o método a seguir à classe como sua função do Azure:

    [FunctionName("Add")]
    public static int Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
    HttpRequestMessage req,
    TraceWriter log)
    {
        int x = 1;
        int y = 2;
    
        return x + y;
    }
    
  5. Vamos examinar a definição do método detalhadamente.

    A primeira coisa que você verá é o atributo FunctionName, que marca este método como uma função do Azure. O atributo designa o nome público da função. O nome do atributo não precisa corresponder ao nome real do método.

    New run method with FunctionName attribute highlighted

  6. Em seguida, o método é marcado como um método estático público, o que é obrigatório. Você também notará que o valor retornado é um int. A menos que seja especificado de outra forma usando atributos de método, qualquer valor retornado não nulo de uma função do Azure será retornado ao cliente como texto. Por padrão, ele é retornado como XML, mas pode ser alterado para JSON, o que você fará mais tarde no laboratório.

    New run method with method initialization highlighted

  7. O primeiro parâmetro é marcado com o atributo HttpTrigger, que indica que esse método é invocado por uma solicitação HTTP. O atributo também especifica o nível de autorização do método, bem como os verbos a que ele dá suporte (apenas "GET" nesse caso). Você também pode definir um Rota que substitui o caminho para o método e oferece uma forma de extrair automaticamente variáveis do caminho. Como o Rota é nula aqui, o caminho para este método terá o valor padrão /api/Add.

    New run method with parameter highlighted

  8. O parâmetro final do método é um TraceWriter, que pode ser usado para registrar mensagens para erros e diagnóstico.

    New run method with TraceWriter highlighted

  9. Defina um ponto de interrupção na linha de retorno do método clicando na margem da linha:

    Breakpoint set at return line

  10. Crie e execute o projeto em uma sessão de depuração pressionando F5 ou selecionando Executar > Iniciar Depuração. Também é possível clicar no botão Executar. Todas essas opções executam a mesma tarefa. O restante deste laboratório faz referência a F5, mas você pode usar o método que considerar mais confortável.

    Build and Run project

  11. Executar o projeto abrirá automaticamente o aplicativo de Terminal.

  12. O projeto passa por um processo de detecção de funções do Azure com base em atributos de método e em uma convenção de arquivo que será abordada posteriormente neste artigo. Nesse caso, ele detecta uma única função do Azure e "gera" 1 função de trabalho.

    Output of Azure function in Terminal

  13. Na parte inferior das mensagens de inicialização, o host do Azure Functions imprime as URLs de qualquer API de gatilho HTTP. Deve haver apenas uma. Copie essa URL e cole-a em uma nova guia do navegador.

    Azure function API URL

  14. O ponto de interrupção deve ser disparado imediatamente. A solicitação da Web foi encaminhada para a função e agora pode ser depurada. Passe o mouse sobre a variável x para ver seu valor.

    Breakpoint triggered

  15. Remova o ponto de interrupção usando o mesmo método usado para adicioná-lo anteriormente (clique na margem ou selecione a linha e pressione F9).

  16. Pressione F5 para continuar a execução.

  17. No navegador, será renderizado o resultado XML do método. Como esperado, a operação de adição codificada produz uma soma plausível. Observe que, se você vir apenas "3" no Safari, acesse Safari > Preferências > Avançado, marque a caixa de seleção "Mostrar menu Desenvolver na barra de menus" e recarregue a página.

  18. No Visual Studio para Mac, clique no botão Parar para encerrar a sessão de depuração. Para garantir que as novas alterações entrem em vigor, não se esqueça de reiniciar (interromper e retomar) a sessão de depuração.

    Stop debugging option

  19. No método Run, substitua as definições de x e y pelo código a seguir. Esse código extrai valores cadeia de consulta da URL para que a operação de adição possa ser realizada de forma dinâmica com base nos parâmetros fornecidos.

    var query = HttpUtility.ParseQueryString(req.RequestUri.Query);
    
    int x = int.Parse(query["x"]);
    
    int y = int.Parse(query["y"]);
    
    return x + y;
    
  20. Executar o aplicativo.

  21. Retorne à janela do navegador e acrescente a cadeia de caracteres /?x=2&y=3 à URL. A URL inteira agora deve ser http://localhost:7071/api/Add?x=2&y=3. Navegue até a nova URL.

  22. Dessa vez, o resultado deve refletir os novos parâmetros. Fique à vontade para executar o projeto com valores diferentes. Observe que não há nenhuma verificação de erros, de modo que parâmetros inválidos ou ausentes gerarão um erro.

  23. Interrompa a sessão de depuração.

Exercício 4: Trabalhar com function.json

  1. Em um exercício anterior, mencionamos que o Visual Studio para Mac “gera” uma função de trabalho para a função do Azure definida na biblioteca. Isso acontece porque o Azure Functions não usa de fato os atributos de método em runtime, mas usa uma convenção de sistema de arquivos em tempo de compilação para configurar onde e como as funções do Azure são disponibilizadas. Na Janela da Solução, clique com o botão direito do mouse no nó do projeto e selecione Revelar no Localizador.

    Reveal in Finder menu option

  2. Navegue pelo sistema de arquivos até alcançar bin/Debug/netstandard2.0. Deve haver uma pasta chamada Add. Essa pasta foi criada para corresponder ao atributo de nome de função no código C#. Expanda a pasta Adicionar para revelar um único arquivo function.json. Esse arquivo é usado pelo runtime para hospedar e gerenciar a função do Azure. Para outros modelos de linguagem sem suporte para tempo de compilação (como script em C# ou JavaScript), essas pastas precisam ser criadas e mantidas manualmente. Para desenvolvedores de C#, elas são geradas automaticamente dos metadados de atributo no momento do build. Clique com o botão direito do mouse em function.json e selecione para abrir no Visual Studio.

    function.json in the file directory

  3. Dadas as etapas anteriores deste tutorial, você deve ter uma compreensão básica dos atributos de C#. Levando isso em conta, este JSON deve ser familiar. No entanto, há alguns itens que não foram abordados em exercícios anteriores. Por exemplo, cada binding precisa ter seu valor de direction definido. Como você pode inferir, "in" significa que o parâmetro é uma entrada, enquanto "out" indica que o parâmetro é um valor retornado (via $return) ou um parâmetro out do método. Você também precisa especificar o scriptFile (relativo a este local final) e o método entryPoint (público e estático) dentro do assembly. Nas próximas etapas, você adicionará um caminho de função personalizado usando este modelo, sendo assim, copie o conteúdo desse arquivo para a área de transferência.

    function.json file open in Visual Studio for mac

  4. Na Janela da Solução, clique com o botão direito do mouse no nó de projeto AzureFunctionsLab e selecione Adicionar > Nova Pasta. Nomeie a nova pasta como Adder. Segundo a convenção padrão, o nome desta pasta definirá o caminho para a API, como api/Adder.

    New folder option

  5. Clique com o botão direito do mouse na pasta Adder e selecione Adicionar > Novo Arquivo.

    New file option

  6. Selecione a categoria Web e o modelo Arquivo JSON Vazio. Defina o Nome como function e clique em Novo.

    Empty json file option

  7. Copie o conteúdo do outro function.json (da etapa 3) para substituir o conteúdo padrão do arquivo recém-criado.

  8. Remova as seguintes linhas da parte superior do arquivo json:

    "configurationSource":"attributes",
    "generatedBy":"Microsoft.NET.Sdk.Functions-1.0.13",
    
  9. No final da primeira associação (após a linha "name": "req"), adicione as propriedades a seguir. Não deixe de incluir uma vírgula na linha anterior. Essa propriedade substitui a raiz padrão, de forma que agora os parâmetros int serão extraídos do caminho e colocados nos parâmetros de método chamados x e y.

    "direction": "in",
    "route": "Adder/{x:int?}/{y:int?}"
    
  10. Adicione outra associação sob a primeira. Essa associação lida com o valor retornado da função. Não deixe de incluir uma vírgula na linha anterior:

    {
    "name": "$return",
    "type": "http",
    "direction": "out"
    }
    
  11. Atualize também a propriedade entryPoint na parte inferior do arquivo para usar um método chamado "Add2", como mostrado abaixo. Isso ilustra que o caminho api/Adder... pode ser mapeado para um método apropriado com qualquer nome (Add2 aqui).

    "entryPoint": "<project-name>.<function-class-name>.Add2"
    
  12. Seu arquivo function.json final deve ser semelhante ao json a seguir:

    {
    "bindings": [
        {
        "type": "httpTrigger",
        "methods": [
            "get"
        ],
        "authLevel": "function",
        "direction": "in",
        "name": "req",
        "route": "Adder/{x:int?}/{y:int?}"
        },
        {
        "name": "$return",
        "type": "http",
        "direction": "out"
        }
    ],
    "disabled": false,
    "scriptFile": "../bin/AzureFunctionsProject.dll",
    "entryPoint": "AzureFunctionsProject.Add.Add2"
    }
    
  13. A etapa final necessária para fazer tudo isso funcionar é instruir o Visual Studio para Mac a copiar esse arquivo para o mesmo caminho relativo no diretório de saída, sempre que ele for alterado. Com o arquivo selecionado, escolha a guia de propriedades na barra direita e, para Copiar para diretório de saída selecione Copiar se mais recente:

    Properties options for json file

  14. Em Add.cs, substitua o método Run (incluindo o atributo) pelo seguinte método para preencher a função esperada. Ele é muito semelhante ao método Run, mas não usa nenhum atributo e tem parâmetros explícitos para x e y.

    public static int Add2(
        HttpRequestMessage req,
        int x,
        int y,
        TraceWriter log)
    {
        return x + y;
    }
    
  15. Pressione F5 para criar e executar o projeto.

  16. Conforme o build é concluído e a plataforma o executa, será indicado que há uma segunda rota disponível para as solicitações, que é mapeada para o método recém-adicionado:

    URL for HTTP functions

  17. Retorne para a janela do navegador e navegue até http://localhost:7071/api/Adder/3/5.

  18. Dessa vez, o método funciona mais uma vez, obtendo os parâmetros do caminho e produzindo uma soma.

  19. Retorne ao Visual Studio para Mac e encerre a sessão de depuração.

Exercício 5: Trabalhar com tabelas do Armazenamento do Azure

Frequentemente, o serviço criado pode ser muito mais complexo do que o que criamos até o momento, e pode demandar tempo ou estrutura significativa para ser executado. Nesse caso, você pode achar eficiente aceitar solicitações enfileiradas para processamento quando os recursos ficarem disponíveis, e o Azure Functions dá suporte a isso. Em outros casos, você vai preferir armazenar dados centralmente. As tabelas de Armazenamento do Azure permitem fazer isso facilmente.

  1. Adicione a classe a seguir a Add.cs. Ela deve ficar dentro do namespace, mas fora da classe atual.

    public class TableRow : TableEntity
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int Sum { get; set; }
    }
    
  2. Dentro da classe Add, adicione o código a seguir para introduzir outra função. Observe que esta é única até o momento, pois não envolve uma resposta HTTP. A linha final retorna uma nova TableRow preenchida com informações de chave que facilitarão a recuperação posteriormente (PartitionKey e RowKey), bem como seus parâmetros e uma soma. O código dentro do método também usa o TraceWriter para ficar mais fácil saber quando a função é executada.

    [FunctionName("Process")]
    [return: Table("Results")]
    public static TableRow Process(
        [HttpTrigger(AuthorizationLevel.Function, "get",
            Route = "Process/{x:int}/{y:int}")]
        HttpRequestMessage req,
        int x,
        int y,
        TraceWriter log)
    {
        log.Info($"Processing {x} + {y}");
    
        return new TableRow()
        {
            PartitionKey = "sums",
            RowKey = $"{x}_{y}",
            X = x,
            Y = y,
            Sum = x + y
        };
    }
    
  3. Pressione F5 para criar e executar o projeto.

  4. Na guia do navegador, navegue até http://localhost:7071/api/Process/4/6. Isso colocará outra mensagem na fila, o que deve fazer com que outra linha seja adicionada à tabela.

  5. Retorne ao Terminal e observe a solicitação de entrada de 4 + 6.

    Terminal output showing addition request

  6. Retorne ao navegador para atualizar a solicitação para a mesma URL. Dessa vez, você verá um erro após o método Process. Isso ocorre porque o método está tentando adicionar uma linha à tabela do Armazenamento de Tabelas do Azure usando uma combinação de partição e chave de linha que já existe.

    System.Private.CoreLib: Exception while executing function: Process. Microsoft.Azure.WebJobs.Host: Error while handling parameter $return after function returned:. Microsoft.Azure.WebJobs.Host: The specified entity already exists.

  7. Encerre a sessão de depuração.

  8. Para mitigar o erro, adicione o seguinte parâmetro à definição de método imediatamente antes do parâmetro TraceWriter. Esse parâmetro instrui a plataforma do Azure Functions a tentar recuperar uma TableRow da tabela de Results na PartitionKey que usamos para armazenar resultados. No entanto, a magia real acontece quando você percebe que RowKey está sendo gerada de forma dinâmica com base nos outros parâmetros x e y do mesmo método. Se essa linha já existir, tableRow a terá quando o método começar sem trabalho extra necessário por parte do desenvolvedor. Se essa linha não existir, o valor será nulo. Esse tipo de eficiência permite que os desenvolvedores se concentrem na lógica de negócios importante, e não na infraestrutura.

    [Table("Results", "sums", "{x}_{y}")]
    TableRow tableRow,
    
  9. Adicione o código a seguir ao início do método. Se tableRow não for nulo, já teremos o resultado da operação solicitada e poderemos retorná-lo imediatamente. Caso contrário, a função continua como antes. Embora essa possa não ser a forma mais robusta de retornar dados, ela ilustra o fato de que é possível orquestrar operações extremamente sofisticadas em várias camadas escalonáveis com pouquíssimo código.

    if (tableRow != null)
    {
        log.Info($"{x} + {y} already exists");
        return null;
    }
    
  10. Pressione F5 para criar e executar o projeto.

  11. Na guia do navegador, atualize a URL em http://localhost:7071/api/Process/4/6. Como a linha da tabela para este registro existe, ela deve ser retornada imediatamente em erros. Como não há uma saída HTTP, você pode ver a saída no Terminal.

    Terminal output showing table row already exists

  12. Atualize a URL para refletir uma combinação que ainda não foi testada, como http://localhost:7071/api/Process/5/7. Observe a mensagem no Terminal, que indica que a linha da tabela não foi encontrada (conforme esperado).

    Terminal output showing new process

  13. Retorne ao Visual Studio para Mac e encerre a sessão de depuração.

Resumo

Neste laboratório, você aprendeu a criar no Azure Functions com o Visual Studio para Mac.