Condividi tramite


Guida introduttiva: Creare una chat room usando Servizio SignalR

Il servizio Azure SignalR è un servizio di Azure che consente agli sviluppatori di compilare facilmente applicazioni Web con funzionalità in tempo reale.

Questo articolo illustra come iniziare a usare il servizio Azure SignalR. In questa guida introduttiva si creerà un'applicazione di chat usando un'app Web ASP.NET Core. Questa app stabilirà una connessione alla risorsa del servizio Azure SignalR per abilitare gli aggiornamenti dei contenuti in tempo reale. L'applicazione Web sarà ospitata in locale e verrà stabilita la connessione con più client browser. Ogni client sarà in grado di eseguire il push degli aggiornamenti dei contenuti a tutti gli altri client.

Per completare i passaggi descritti in questa guida di avvio rapido è possibile usare qualsiasi editor di codice. Una scelta possibile è Visual Studio Code, disponibile per le piattaforme Windows, macOS e Linux.

Il codice per questa esercitazione è disponibile per il download nel repository GitHub AzureSignalR-samples. È possibile creare le risorse di Azure usate in questa guida introduttiva seguendo creare uno script di Servizio SignalR.

Se non si ha una sottoscrizione di Azure, creare un account gratuito prima di iniziare.

Importante

Le stringa di connessione non elaborate vengono visualizzate in questo articolo solo a scopo dimostrativo.

Una stringa di connessione include le informazioni sull'autorizzazione necessarie all'applicazione per l'accesso al servizio Azure Web PubSub. La chiave di accesso all'interno della stringa di connessione è simile a una password radice per il servizio. Negli ambienti di produzione proteggere sempre le chiavi di accesso. Usare Azure Key Vault per gestire e ruotare le chiavi in modo sicuro e proteggere i stringa di connessione usando Microsoft Entra ID e autorizzare l'accesso con Microsoft Entra ID.

Evitare di distribuire le chiavi di accesso ad altri utenti, impostarle come hardcoded o salvarle in un file di testo normale accessibile ad altri. Ruotare le chiavi se si ritiene che siano state compromesse.

Pronti a iniziare?

Prerequisiti

Problemi? Vedere la guida alla risoluzione dei problemi oppure segnalarli.

Creare una risorsa di Azure SignalR

In questa sezione viene creata un'istanza di Azure SignalR di base da usare per l'app. I passaggi seguenti usano il portale di Azure per creare una nuova istanza, ma è anche possibile usare l'interfaccia della riga di comando di Azure. Per altre informazioni, vedere il comando az signalr create in Informazioni di riferimento sull'interfaccia della riga di comando per il Servizio Azure SignalR.

  1. Accedere al portale di Azure.
  2. Nell'angolo in alto a sinistra della pagina selezionare + Crea una risorsa.
  3. Nella casella di testo Servizi di ricerca e marketplace della pagina Crea una risorsa immettere signalr e quindi selezionare Servizio SignalR dall'elenco.
  4. Nella pagina Servizio SignalR selezionare Crea.
  5. Nella scheda Informazioni di base immettere le informazioni essenziali per la nuova istanza del servizio SignalR. Immettere i valori seguenti:
Campo Valore consigliato Descrizione
Abbonamento Scegliere la sottoscrizione in uso Selezionare la sottoscrizione da usare per creare una nuova istanza del servizio SignalR.
Gruppo di risorse Creare un gruppo di risorse denominato SignalRTestResources Selezionare o creare un gruppo di risorse per la risorsa SignalR. È utile creare un nuovo gruppo di risorse per questa esercitazione anziché usare un gruppo di risorse esistente. Per liberare risorse dopo aver completato l'esercitazione, eliminare il gruppo di risorse.

L'eliminazione di un gruppo di risorse elimina anche tutte le risorse che appartengono al gruppo. Non è possibile annullare questa azione. Prima di eliminare un gruppo di risorse, assicurarsi che non contenga risorse da conservare.

Per altre informazioni, vedere Using resource groups to manage your Azure resources (Uso di Gruppi di risorse per gestire le risorse di Azure).
Nome risorsa testsignalr Immettere un nome risorsa univoco da usare per la risorsa SignalR. Se testsignalr è già in uso nell'area, aggiungere una cifra o un carattere fino a quando il nome non è univoco.

Il nome deve essere una stringa contenente da 1 a 63 caratteri che possono includere solo numeri, lettere e il segno meno (-). Il nome non può iniziare o terminare con un trattino e non sono consentiti più trattini consecutivi.
Area Scegli la tua area geografica Selezionare l'area appropriata per la nuova istanza del servizio SignalR.

Il Servizio Azure SignalR non è attualmente disponibile in tutte le aree. Per altre informazioni, vedere Disponibilità del Servizio Azure SignalR a livello di area
Piano tariffario Selezionare Modifica e quindi scegliere Gratuito (solo sviluppo/test). Scegliere Seleziona per confermare la scelta del piano tariffario. Il Servizio Azure SignalR ha tre piani tariffari: Gratuito, Standard e Premium. Le esercitazioni usano il livello Gratuito, a meno che non sia specificato diversamente nei prerequisiti.

Per altre informazioni sulle differenze di funzionalità tra i livelli e i prezzi, vedere Prezzi del Servizio Azure SignalR
Modalità di servizio Scegliere la modalità di servizio appropriata Usare Predefinita quando si ospita la logica dell'hub SignalR nelle app Web e si usa il Servizio SignalR come proxy. Usare Serverless quando si usano tecnologie serverless come Funzioni di Azure per ospitare la logica dell'hub SignalR.

La modalità Classica è disponibile solo ai fini della compatibilità con le versioni precedenti e non è consigliabile usarla.

Per altre informazioni, vedere Modalità di servizio nel Servizio Azure SignalR.

Non è necessario modificare le impostazioni nelle schede Rete e Tag per le esercitazioni su SignalR.

  1. Selezionare il pulsante blu Rivedi e crea nella parte inferiore della scheda Informazioni di base.
  2. Nella scheda Rivedi e crea rivedere i valori e quindi selezionare Crea. Il completamento della distribuzione richiede alcuni istanti.
  3. Dopo avere completato la distribuzione, selezionare il pulsante Vai alla risorsa.
  4. Nella pagina della risorsa SignalR selezionare Chiavi dal menu a sinistra, in Impostazioni.
  5. Copiare la Stringa di connessione per la chiave primaria. Questa stringa di connessione è necessaria per configurare l'app più avanti in questa esercitazione.

Creare un'app Web ASP.NET Core

In questa sezione verrà usata l'interfaccia della riga di comando di .NET Core per creare un progetto di app Web ASP.NET Core MVC. Il vantaggio di usare l'interfaccia della riga di comando di .NET Core rispetto a Visual Studio è che è disponibile nelle piattaforme Windows, macOS e Linux.

  1. Creare una cartella per il progetto. Questa guida introduttiva usa la cartella chattest .

  2. Nella nuova cartella eseguire il comando seguente per creare il progetto:

    dotnet new web
    

Aggiungere Secret Manager al progetto

In questa sezione verrà aggiunto lo strumento Secret Manager al progetto. Lo strumento Secret Manager archivia i dati sensibili per operazioni di sviluppo al di fuori dell'albero del progetto. Questo approccio contribuisce a impedire la condivisione accidentale dei segreti dell'app nel codice sorgente.

  1. Nella cartella init UserSecretsId eseguire il comando seguente:

    dotnet user-secrets init
    
  2. Aggiungere un segreto denominato Azure:SignalR:ConnectionString a Secret Manager.

    Le stringa di connessione non elaborate vengono visualizzate in questo articolo solo a scopo dimostrativo. Negli ambienti di produzione proteggere sempre le chiavi di accesso. Usare Azure Key Vault per gestire e ruotare le chiavi in modo sicuro e proteggere i stringa di connessione usando Microsoft Entra ID e autorizzare l'accesso con Microsoft Entra ID.

    Questo segreto conterrà la stringa di connessione per accedere alla risorsa del servizio SignalR. Azure:SignalR:ConnectionString è la chiave di configurazione predefinita cercata da SignalR per stabilire una connessione. Sostituire il valore nel comando seguente con la stringa di connessione per la propria risorsa del servizio SignalR.

    È necessario eseguire questo comando nella stessa directory del csproj file.

    dotnet user-secrets set Azure:SignalR:ConnectionString "<Your connection string>"
    

    Secret Manager verrà usato solo per il test dell'app Web mentre è ospitata in locale. In un'esercitazione successiva si distribuirà l'app Web di chat in Azure. Dopo la distribuzione dell'app Web in Azure, sarà possibile usare un'impostazione dell'applicazione invece di archiviare la stringa di connessione con Secret Manager.

    È possibile accedere al segreto con l'API di configurazione. Con tale API è possibile usare i due punti (:) nel nome di configurazione in tutte le piattaforme supportate. Vedere la configurazione in base all'ambiente.

Aggiungere Azure SignalR all'app Web

  1. Aggiungere un riferimento al pacchetto NuGet Microsoft.Azure.SignalR eseguendo il comando seguente:

    dotnet add package Microsoft.Azure.SignalR
    
  2. Aprire Program.cs e aggiornare il codice al codice seguente, chiama i AddSignalR() metodi e AddAzureSignalR() per usare Servizio Azure SignalR:

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddSignalR().AddAzureSignalR();
    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseRouting();
    app.UseStaticFiles();
    app.MapHub<ChatSampleHub>("/chat");
    app.Run();
    

    Non passando un parametro a AddAzureSignalR() significa che usa la chiave di configurazione predefinita per la risorsa Servizio SignalR stringa di connessione. La chiave di configurazione predefinita è Azure:SignalR:ConnectionString. Viene usato anche ChatSampleHub il quale verrà creato nella sezione seguente.

Aggiungere una classe hub

In SignalR un hub è un componente di base che espone un set di metodi che possono essere chiamati dal client. In questa sezione si definisce una classe hub con due metodi:

  • BroadcastMessage: questo metodo trasmette un messaggio a tutti i client.
  • Echo: questo metodo invia un messaggio al chiamante.

Entrambi i metodi usano l'interfaccia Clients fornita da ASP.NET Core SignalR SDK. Questa interfaccia consente di accedere a tutti i client connessi, rendendo possibile il push del contenuto ai client.

  1. Nella directory del progetto aggiungere una nuova cartella denominata Hub. Aggiungere un nuovo file di codice hub denominato ChatSampleHub.cs alla nuova cartella.

  2. Aggiungere il codice seguente per ChatSampleHub.cs per definire la classe hub e salvare il file.

    using Microsoft.AspNetCore.SignalR;
    
    public class ChatSampleHub : Hub
    {
        public Task BroadcastMessage(string name, string message) =>
            Clients.All.SendAsync("broadcastMessage", name, message);
    
        public Task Echo(string name, string message) =>
            Clients.Client(Context.ConnectionId)
                    .SendAsync("echo", name, $"{message} (echo from server)");
    }
    

Aggiungere l'interfaccia client per l'app Web

L'interfaccia utente client per questa app di chat room sarà costituita da HTML e JavaScript in un file denominato index.html nella directory wwwroot.

Copiare il file css/site.css dalla cartella wwwroot del repository degli esempi. Sostituire il file css/site.css del progetto con quello copiato.

Creare un nuovo file nella directory wwwroot denominata index.html, copiare e incollare il codice HTML seguente nel file appena creato.

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
  <meta name="viewport" content="width=device-width">
  <meta http-equiv="Pragma" content="no-cache" />
  <meta http-equiv="Expires" content="0" />
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
  <link href="css/site.css" rel="stylesheet" />
  <title>Azure SignalR Group Chat</title>
</head>
<body>
  <h2 class="text-center" style="margin-top: 0; padding-top: 30px; padding-bottom: 30px;">Azure SignalR Group Chat</h2>
  <div class="container" style="height: calc(100% - 110px);">
    <div id="messages" style="background-color: whitesmoke; "></div>
    <div style="width: 100%; border-left-style: ridge; border-right-style: ridge;">
      <textarea id="message" style="width: 100%; padding: 5px 10px; border-style: hidden;"
        placeholder="Type message and press Enter to send..."></textarea>
    </div>
    <div style="overflow: auto; border-style: ridge; border-top-style: hidden;">
      <button class="btn-warning pull-right" id="echo">Echo</button>
      <button class="btn-success pull-right" id="sendmessage">Send</button>
    </div>
  </div>
  <div class="modal alert alert-danger fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <div>Connection Error...</div>
          <div><strong style="font-size: 1.5em;">Hit Refresh/F5</strong> to rejoin. ;)</div>
        </div>
      </div>
    </div>
  </div>

  <!--Reference the SignalR library. -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>

  <!--Add script to update the page and send messages.-->
  <script type="text/javascript">
    document.addEventListener("DOMContentLoaded", function () {
      function getUserName() {
        function generateRandomName() {
          return Math.random().toString(36).substring(2, 10);
        }

        // Get the user name and store it to prepend to messages.
        var username = generateRandomName();
        var promptMessage = "Enter your name:";
        do {
          username = prompt(promptMessage, username);
          if (!username || username.startsWith("_") || username.indexOf("<") > -1 || username.indexOf(">") > -1) {
            username = "";
            promptMessage = "Invalid input. Enter your name:";
          }
        } while (!username)
        return username;
      }

      username = getUserName();
      // Set initial focus to message input box.
      var messageInput = document.getElementById("message");
      messageInput.focus();

      function createMessageEntry(encodedName, encodedMsg) {
        var entry = document.createElement("div");
        entry.classList.add("message-entry");
        if (encodedName === "_SYSTEM_") {
          entry.innerHTML = encodedMsg;
          entry.classList.add("text-center");
          entry.classList.add("system-message");
        } else if (encodedName === "_BROADCAST_") {
          entry.classList.add("text-center");
          entry.innerHTML = `<div class="text-center broadcast-message">${encodedMsg}</div>`;
        } else if (encodedName === username) {
          entry.innerHTML = `<div class="message-avatar pull-right">${encodedName}</div>` +
            `<div class="message-content pull-right">${encodedMsg}<div>`;
        } else {
          entry.innerHTML = `<div class="message-avatar pull-left">${encodedName}</div>` +
            `<div class="message-content pull-left">${encodedMsg}<div>`;
        }
        return entry;
      }

      function appendMessage(encodedName, encodedMsg) {
        var messageEntry = createMessageEntry(encodedName, encodedMsg);
        var messageBox = document.getElementById("messages");
        messageBox.appendChild(messageEntry);
        messageBox.scrollTop = messageBox.scrollHeight;
      }

      function bindConnectionMessage(connection) {
        var messageCallback = function (name, message) {
          if (!message) return;
          // Html encode display name and message.
          var encodedName = name;
          var encodedMsg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
          appendMessage(encodedName, encodedMsg);
        };
        // Create a function that the hub can call to broadcast messages.
        connection.on("broadcastMessage", messageCallback);
        connection.on("echo", messageCallback);
        connection.onclose(onConnectionError);
      }

      function onConnected(connection) {
        console.log("connection started");
        connection.send("broadcastMessage", "_SYSTEM_", username + " JOINED");
        document.getElementById("sendmessage").addEventListener("click", function (event) {
          // Call the broadcastMessage method on the hub.
          if (messageInput.value) {
            connection.send("broadcastMessage", username, messageInput.value)
              .catch((e) => appendMessage("_BROADCAST_", e.message));
          }

          // Clear text box and reset focus for next comment.
          messageInput.value = "";
          messageInput.focus();
          event.preventDefault();
        });
        document.getElementById("message").addEventListener("keypress", function (event) {
          if (event.keyCode === 13) {
            event.preventDefault();
            document.getElementById("sendmessage").click();
            return false;
          }
        });
        document.getElementById("echo").addEventListener("click", function (event) {
          // Call the echo method on the hub.
          connection.send("echo", username, messageInput.value);

          // Clear text box and reset focus for next comment.
          messageInput.value = "";
          messageInput.focus();
          event.preventDefault();
        });
      }

      function onConnectionError(error) {
        if (error && error.message) {
          console.error(error.message);
        }
        var modal = document.getElementById("myModal");
        modal.classList.add("in");
        modal.style = "display: block;";
      }

      var connection = new signalR.HubConnectionBuilder()
        .withUrl("/chat")
        .build();
      bindConnectionMessage(connection);
      connection.start()
        .then(function () {
          onConnected(connection);
        })
        .catch(function (error) {
          console.error(error.message);
        });
    });
  </script>
</body>
</html>

Il codice in index.html chiama HubConnectionBuilder.build() per stabilire una connessione HTTP alla risorsa di Azure SignalR.

Se la connessione ha esito positivo, viene passata a bindConnectionMessage, che consente di aggiungere i gestori di eventi per i push dei contenuti in ingresso al client.

HubConnection.start() avvia la comunicazione con l'hub. onConnected() quindi aggiunge i gestori eventi del pulsante. Questi gestori usano la connessione per consentire a questo client di eseguire il push degli aggiornamenti dei contenuti a tutti i client connessi.

Compilare ed eseguire l'app in locale

  1. Eseguire il comando seguente per eseguire l'app Web in locale:

    dotnet run
    

    L'app verrà ospitata in locale con output contenente l'URL localhost, ad esempio, come indicato di seguito:

    Building...
    info: Microsoft.Hosting.Lifetime[14]
          Now listening on: http://localhost:5000
    info: Microsoft.Hosting.Lifetime[0]
          Application started. Press Ctrl+C to shut down.
    info: Microsoft.Hosting.Lifetime[0]
          Hosting environment: Development
    
  2. Aprire due finestre del browser. In ogni browser passare all'URL localhost visualizzato nella finestra di output, ad esempio, http://localhost:5000/ come illustrato nella finestra di output precedente. Verrà richiesto di immettere il proprio nome. Immettere un nome per entrambi i client e verificare il push del contenuto del messaggio tra i due client usando il pulsante Invia.

    Esempio di chat di gruppo di Azure SignalR

Pulire le risorse

Se si proseguirà con l'esercitazione successiva, sarà possibile conservare le risorse create in questo argomento di avvio rapido e riutilizzarle.

Se si è terminato di lavorare con l'applicazione di esempio di avvio rapido, è possibile eliminare le risorse di Azure create in questo argomento di avvio rapido per evitare i costi correlati.

Importante

L'eliminazione di un gruppo di risorse è irreversibile e interessa tutte le risorse del gruppo. Assicurarsi di non eliminare accidentalmente il gruppo di risorse sbagliato o le risorse errate. Se sono state create le risorse in questo esempio in un gruppo di risorse esistente che contiene risorse da conservare, è possibile eliminare ogni risorsa singolarmente dal relativo pannello anziché eliminare il gruppo di risorse.

Accedere al portale di Azure e selezionare Gruppi di risorse.

Nella casella di testo Filtra per nome digitare il nome del gruppo di risorse. Per le istruzioni di questa guida introduttiva è stato usato un gruppo di risorse denominato SignalRTestResources. Nel gruppo di risorse nell'elenco dei risultati selezionare i puntini di sospensione (...) >Eliminare un gruppo di risorse.

Selezioni per eliminare un gruppo di risorse

Verrà chiesto di confermare l'eliminazione del gruppo di risorse. Immettere il nome del gruppo di risorse per confermare e selezionare Elimina.

Dopo qualche istante, il gruppo di risorse e tutte le risorse che contiene vengono eliminati.

Problemi? Vedere la guida alla risoluzione dei problemi oppure segnalarli.

Passaggi successivi

In questo argomento di avvio rapido è stata creata una nuova risorsa del servizio Azure SignalR È stata quindi usata con un'app Web ASP.NET Core per eseguire il push degli aggiornamenti del contenuto in tempo reale a più client connessi. Per altre informazioni sull'uso del servizio Azure SignalR, continuare con l'esercitazione sull'autenticazione.