Compartilhar via


Guia de Início Rápido: Criar um aplicativo que mostra a contagem de estrelas do GitHub com o Azure Functions e o Serviço do SignalR usando o C#

Neste artigo, você aprenderá a usar o Serviço do SignalR e o Azure Functions para criar um aplicativo sem servidor com o C# a fim de transmitir mensagens aos clientes.

Observação

Obtenha o código mencionado neste artigo no GitHub.

Importante

Cadeias de conexão brutas aparecem neste artigo somente para fins de demonstração.

Uma cadeia de conexão inclui as informações de autorização necessárias para que o seu aplicativo acesse o serviço Azure Web PubSub. A chave de acesso dentro da cadeia de conexão é semelhante a uma senha raiz para o serviço. Em ambientes de produção, sempre proteja suas chaves de acesso. Use o Azure Key Vault para gerenciar e girar suas chaves com segurança e proteger sua cadeia de conexão usando o Microsoft Entra ID.

Evite distribuir chaves de acesso para outros usuários, fazer hard-coding com elas ou salvá-las em qualquer lugar em texto sem formatação que seja acessível a outras pessoas. Gire suas chaves se você acredita que elas podem ter sido comprometidas.

Pré-requisitos

Os seguintes pré-requisitos são necessários para este guia de início rápido:

Criar uma instância do Serviço Azure SignalR

Nesta seção, você cria uma instância básica do Azure SignalR para usar em seu aplicativo. As etapas a seguir usam o portal do Azure para criar uma nova instância, mas você também pode usar a CLI do Azure. Para obter mais informações, consulte o comando az signalr create na referência da CLI do serviço do Azure SignalR.

  1. Entre no portal do Azure.
  2. No canto superior esquerdo da página, escolha + Criar um recurso.
  3. Na página Criar um recurso, na caixa de texto serviços Pesquisa e marketplace, insira signalr e, em seguida, selecione Serviço do SignalR na lista.
  4. Na página Serviço do SignalR, selecione Criar.
  5. Na guia Noções básicas, você insere as informações essenciais para a nova instância do Serviço do SignalR. Insira os valores a seguir:
Campo Valor sugerido Descrição
Assinatura Escolha sua assinatura Selecione a assinatura que você deseja usar para criar uma nova instância do serviço do SignalR.
Grupo de recursos Criar um grupo de recursos chamado SignalRTestResources Selecione ou crie um grupo de recursos para seu recurso do SignalR. É útil criar um novo grupo de recursos para este tutorial em vez de usar um grupo de recursos existente. Para liberar recursos depois de concluir o tutorial, exclua o grupo de recursos.

A exclusão de um grupo de recursos também exclui todos os recursos que pertencem ao grupo. Essa ação não pode ser desfeita. Antes de excluir um grupo de recursos, certifique-se de que ele não contenha os recursos que você deseja manter.

Para obter mais informações, consulte Usando os grupos de recursos para gerenciar seus recursos do Azure.
Nome do recurso testsignalr Insira um nome exclusivo do recurso a ser usado para o recurso do SignalR. Se testsignalr já estiver sendo usado em sua região, adicione um dígito ou caractere até que o nome seja exclusivo.

O nome deve ser uma cadeia de caracteres com 1 a 63 caracteres, e deve conter somente números, letras e o hífen (-). O nome não pode começar nem terminar com o caractere hífen, e os caracteres hífen consecutivos não serão válidos.
Região Escolha a região Selecione a região apropriada para sua nova instância do serviço do SignalR.

O serviço do Azure SignalR não está disponível atualmente em todas as regiões. Para saber mais, confira Disponibilidade por região do serviço do Azure SignalR
Tipo de preços Selecione Alterar e, em seguida, escolha Gratuito (somente desenvolvimento/teste). Escolha Selecionar para confirmar sua escolha de tipo de preço. O serviço do Azure SignalR tem três tipos de preço: Gratuito, Standard e Premium. Os tutoriais usam o tipo Gratuito, a menos que indicado de outra forma nos pré-requisitos.

Para obter mais informações sobre as diferenças de funcionalidade entre tipos e preços, consulte preço do serviço do Azure SignalR
Modo de serviço Escolha o modo de serviço apropriado Use Padrão quando hospedar a lógica do hub do SignalR em seus aplicativos Web e usar o serviço SignalR como um proxy. Use Sem servidor quando usar tecnologias sem servidor, como o Azure Functions, para hospedar a lógica do hub do SignalR.

O modo Clássico é apenas para compatibilidade com versões anteriores e não é recomendável usar.

Para obter mais informações, confira Modo de serviço no serviço do Azure SignalR.

Você não precisa alterar as configurações nas guias Rede e Marcações para os tutoriais do SignalR.

  1. Selecione o botão Revisar + criar na parte inferior da guia Noções básicas.
  2. Na guia Revisar + Criar, revise os valores e, em seguida, selecione Criar. A implantação leva alguns momentos para ser concluída.
  3. Depois que a implantação estiver concluída, selecione o botão Ir para o recurso.
  4. Na tela de recursos do SignalR, selecione Chaves no menu à esquerda, em Configurações.
  5. Copie a Cadeia de conexão para a chave primária. Você precisa dessa cadeia de conexão para configurar seu aplicativo posteriormente neste tutorial.

Configurar e executar a Azure Function localmente

Você precisará do Azure Functions Core Tools para esta etapa.

  1. Crie um diretório vazio e navegue até o diretório com uma linha de comando.

  2. Inicializar um novo projeto.

    # Initialize a function project
    func init --worker-runtime dotnet
    
    # Add SignalR Service package reference to the project
    dotnet add package Microsoft.Azure.WebJobs.Extensions.SignalRService
    
  3. Usando o editor de código, crie um arquivo com o nome Function.cs. Adicione o seguinte código a Function.cs:

    using System;
    using System.IO;
    using System.Linq;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Azure.WebJobs.Extensions.SignalRService;
    using Newtonsoft.Json;
    
    namespace CSharp
    {
        public static class Function
        {
            private static HttpClient httpClient = new HttpClient();
            private static string Etag = string.Empty;
            private static string StarCount = "0";
    
            [FunctionName("index")]
            public static IActionResult GetHomePage([HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req, ExecutionContext context)
            {
                var path = Path.Combine(context.FunctionAppDirectory, "content", "index.html");
                return new ContentResult
                {
                    Content = File.ReadAllText(path),
                    ContentType = "text/html",
                };
            }
    
            [FunctionName("negotiate")]
            public static SignalRConnectionInfo Negotiate(
                [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
                [SignalRConnectionInfo(HubName = "serverless")] SignalRConnectionInfo connectionInfo)
            {
                return connectionInfo;
            }
    
            [FunctionName("broadcast")]
            public static async Task Broadcast([TimerTrigger("*/5 * * * * *")] TimerInfo myTimer,
            [SignalR(HubName = "serverless")] IAsyncCollector<SignalRMessage> signalRMessages)
            {
                var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/azure/azure-signalr");
                request.Headers.UserAgent.ParseAdd("Serverless");
                request.Headers.Add("If-None-Match", Etag);
                var response = await httpClient.SendAsync(request);
                if (response.Headers.Contains("Etag"))
                {
                    Etag = response.Headers.GetValues("Etag").First();
                }
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    var result = JsonConvert.DeserializeObject<GitResult>(await response.Content.ReadAsStringAsync());
                    StarCount = result.StarCount;
                }
    
                await signalRMessages.AddAsync(
                    new SignalRMessage
                    {
                        Target = "newMessage",
                        Arguments = new[] { $"Current star count of https://github.com/Azure/azure-signalr is: {StarCount}" }
                    });
            }
    
            private class GitResult
            {
                [JsonRequired]
                [JsonProperty("stargazers_count")]
                public string StarCount { get; set; }
            }
        }
    }
    

    O código de Function.cs tem três funções:

    • GetHomePage é usado para obter um site como cliente.
    • Negotiate é usado pelo cliente para obter um token de acesso.
    • Broadcast é periodicamente chamado para obter a contagem de estrelas do GitHub e difundir mensagens para todos os clientes.
  4. A interface do cliente deste exemplo é uma página da Web. Renderizamos a página da Web usando a função GetHomePage lendo o conteúdo HTML do arquivo content/index.html. Agora vamos criar este index.html no subdiretório content com o seguinte conteúdo:

    <html>
    
    <body>
      <h1>Azure SignalR Serverless Sample</h1>
      <div id="messages"></div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.min.js"></script>
      <script>
        let messages = document.querySelector('#messages');
        const apiBaseUrl = window.location.origin;
        const connection = new signalR.HubConnectionBuilder()
            .withUrl(apiBaseUrl + '/api')
            .configureLogging(signalR.LogLevel.Information)
            .build();
          connection.on('newMessage', (message) => {
            document.getElementById("messages").innerHTML = message;
          });
    
          connection.start()
            .catch(console.error);
      </script>
    </body>
    
    </html>
    
  5. Atualize o *.csproj para criar a página de conteúdo na pasta de saída do build.

    <ItemGroup>
      <None Update="content/index.html">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
    </ItemGroup>
    
  6. O Azure Functions exige uma conta de armazenamento para funcionar. Você pode instalar e executar o Emulador do Armazenamento do Azure. Ou você pode atualizar a configuração para usar sua conta de armazenamento real com o seguinte comando:

    func settings add AzureWebJobsStorage "<storage-connection-string>"
    
  7. Agora, está quase pronto. A última etapa é definir uma cadeia de conexão do Serviço do SignalR para as configurações do Azure Function.

    1. Confirme se a instância do Serviço do SignalR foi criada com êxito procurando o nome dela na caixa de pesquisa na parte superior do portal. Selecione a instância para abri-la.

      Pesquisar a instância do SignalR Service

    2. Selecione Chaves para exibir as cadeias de conexão para a instância do SignalR Service.

      Captura de tela que realça a cadeia de conexão primária.

    3. Copie a cadeia de conexão primária e execute o comando a seguir.

      Cadeias de conexão brutas aparecem neste artigo somente para fins de demonstração. Em ambientes de produção, sempre proteja suas chaves de acesso. Use o Azure Key Vault para gerenciar e girar suas chaves com segurança e proteger sua cadeia de conexão usando o Microsoft Entra ID.

      func settings add AzureSignalRConnectionString "<signalr-connection-string>"
      
  8. Execute a função do Azure localmente:

    func start
    

    Depois que a função do Azure estiver em execução localmente, abra http://localhost:7071/api/index e você poderá ver a contagem de estrelas atual. Se você adicionar ou remover uma estrela no GitHub, obterá uma contagem de estrelas atualizada em intervalos de alguns segundos.

Limpar os recursos

Se você não pretende continuar a usar este aplicativo, exclua todos os recursos criados por esse início rápido com as seguintes etapas para não incorrer em alterações:

  1. No portal do Azure, selecione Grupos de recursos na extremidade esquerda, depois selecione o recurso de grupo que você criou. Como alternativa, você pode usar a caixa de pesquisa para localizar o grupo de recursos pelo nome.

  2. Na janela que se abre, selecione o grupo de recursos e clique em Excluir grupo de recursos.

  3. Na nova janela, digite o nome do grupo de recursos a ser excluído, depois clique em Excluir.

Está com problemas? Experimente o guia de solução de problemas ou fale conosco.

Próximas etapas

Neste guia de início rápido, você criou e executou um aplicativo sem servidor em tempo real localmente. A seguir, saiba mais sobre a comunicação bidirecional entre os clientes e o Azure Functions com o Serviço do Azure SignalR.