Esercitazione: Introduzione a ASP.NET Core SignalR con TypeScript e Webpack

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Di Sébastien Sougnez

Questa esercitazione illustra l'uso di Webpack in un'app Web ASP.NET Core SignalR per aggregare e compilare un client scritto in TypeScript. Webpack consente agli sviluppatori di creare un bundle delle risorse di un'app Web sul lato client-e di compilarle.

In questa esercitazione apprenderai a:

  • Creare un'app ASP.NET Core SignalR
  • Configurare il SignalR server
  • Configurare una pipeline di compilazione tramite Webpack
  • Configurare il SignalR client TypeScript
  • Abilitare la comunicazione tra il client e il server

Visualizzare o scaricare il codice di esempio (procedura per il download)

Prerequisiti

Creare l'app Web ASP.NET Core

Per impostazione predefinita, Visual Studio usa la versione di npm trovata nella directory di installazione. Per configurare Visual Studio per cercare npm nella PATH variabile di ambiente:

Avviare Visual Studio. Nella finestra iniziale selezionare Continua senza codice.

  1. Passare a Strumenti>Opzioni>Progetti e soluzioni>Gestione pacchetti Web>Strumenti Web esterni.

  2. Selezionare la $(PATH) voce dall'elenco. Selezionare la freccia su per spostare la voce nella seconda posizione nell'elenco e selezionare OK:

    Configurazione di Visual Studio.

Per creare una nuova app Web ASP.NET Core:

  1. Usare l'opzione di menu File>nuovo>progetto e scegliere il modello ASP.NET core vuoto. Selezionare Avanti.
  2. Assegnare al progetto SignalRWebpackil nome e selezionare Crea.
  3. Selezionare .NET 8.0 (supporto a lungo termine) dall'elenco a discesa Framework . Seleziona Crea.

Aggiungere il pacchetto NuGet Microsoft.TypeScript.MSBuild al progetto:

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Gestisci pacchetti NuGet. Nella scheda Sfoglia cercare Microsoft.TypeScript.MSBuild e quindi selezionare Installa a destra per installare il pacchetto.

Visual Studio aggiunge il pacchetto NuGet nel nodo Dipendenze in Esplora soluzioni, abilitando la compilazione TypeScript nel progetto.

Configurare il server

In questa sezione viene configurata l'app Web ASP.NET Core per inviare e ricevere SignalR messaggi.

  1. In Program.cschiamare AddSignalR:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddSignalR();
    
  2. Anche in Program.cs, chiamare UseDefaultFiles e UseStaticFiles:

    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    

    Il codice precedente consente al server di individuare e gestire il index.html file. Il file viene gestito indipendentemente dal fatto che l'utente immetta l'URL completo o l'URL radice dell'app Web.

  3. Creare una nuova directory denominata Hubs nella radice del progetto, SignalRWebpack/, per la SignalR classe hub.

  4. Creare un nuovo file, Hubs/ChatHub.cs, con il codice seguente:

    using Microsoft.AspNetCore.SignalR;
    
    namespace SignalRWebpack.Hubs;
    
    public class ChatHub : Hub
    {
        public async Task NewMessage(long username, string message) =>
            await Clients.All.SendAsync("messageReceived", username, message);
    }
    

    Il codice precedente trasmette i messaggi ricevuti a tutti gli utenti connessi dopo che il server li riceve. Non è necessario avere un metodo generico on per ricevere tutti i messaggi. Un metodo denominato dopo il nome del messaggio è sufficiente.

    In questo esempio:

    • Il client TypeScript invia un messaggio identificato come newMessage.
    • Il metodo C# NewMessage si aspetta i dati inviati dal client.
    • Viene effettuata una chiamata a SendAsync su Clients.All.
    • I messaggi ricevuti vengono inviati a tutti i client connessi all'hub.
  5. Aggiungere l'istruzione seguente using all'inizio di Program.cs per risolvere il ChatHub riferimento:

    using SignalRWebpack.Hubs;
    
  6. In Program.cseseguire il mapping della /hub route all'hub ChatHub . Sostituire il codice visualizzato Hello World! con il codice seguente:

    app.MapHub<ChatHub>("/hub");
    

Configurare il client

In questa sezione viene creato un progetto Node.js per convertire TypeScript in JavaScript e aggregare le risorse lato client, incluso HTML e CSS, usando Webpack.

  1. Eseguire il comando seguente nella radice del progetto per creare un package.json file:

    npm init -y
    
  2. Aggiungere la proprietà evidenziata al package.json file e salvare le modifiche apportate al file:

    {
      "name": "SignalRWebpack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Impostando la proprietà private su true si evita la visualizzazione di avvisi di installazione del pacchetto nel passaggio successivo.

  3. Installare i pacchetti npm necessari. Eseguire il comando seguente dalla radice del progetto:

    npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
    

    L'opzione -E disabilita il comportamento predefinito di npm per la scrittura di operatori di intervallo di controllo delle versioni semantici in package.json. Ad esempio, viene usato "webpack": "5.76.1" invece di "webpack": "^5.76.1". Questa opzione impedisce che vengano eseguiti aggiornamenti non desiderati a versioni più recenti del pacchetto.

    Per altre informazioni, vedere la documentazione di npm-install .

  4. Sostituire la scripts proprietà del package.json file con il codice seguente:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Vengono definiti gli script seguenti:

    • build: raggruppa le risorse lato client in modalità di sviluppo e controlla le modifiche dei file. Questo controllo fa sì che il bundle venga rigenerato a ogni modifica del file di progetto. L'opzione mode disabilita le ottimizzazioni di produzione, come l'eliminazione del codice non utilizzato e la minimizzazione. uso build solo in fase di sviluppo.
    • release: raggruppa le risorse lato client in modalità di produzione.
    • publish: esegue lo script release per creare il bundle delle risorse sul lato client in modalità di produzione. Chiama il comando publish dell'interfaccia della riga di comando di .NET per pubblicare l'app.
  5. Creare un file denominato webpack.config.js nella radice del progetto con il codice seguente:

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const { CleanWebpackPlugin } = require("clean-webpack-plugin");
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    module.exports = {
        entry: "./src/index.ts",
        output: {
            path: path.resolve(__dirname, "wwwroot"),
            filename: "[name].[chunkhash].js",
            publicPath: "/",
        },
        resolve: {
            extensions: [".js", ".ts"],
        },
        module: {
            rules: [
                {
                    test: /\.ts$/,
                    use: "ts-loader",
                },
                {
                    test: /\.css$/,
                    use: [MiniCssExtractPlugin.loader, "css-loader"],
                },
            ],
        },
        plugins: [
            new CleanWebpackPlugin(),
            new HtmlWebpackPlugin({
                template: "./src/index.html",
            }),
            new MiniCssExtractPlugin({
                filename: "css/[name].[chunkhash].css",
            }),
        ],
    };
    

    Il file precedente configura il processo di compilazione Webpack:

    • La output proprietà esegue l'override del valore predefinito di dist. Il bundle viene invece generato nella wwwroot directory .
    • La resolve.extensions matrice include .js per importare il SignalR client JavaScript.
  6. Creare una nuova directory denominata src nella radice del progetto, SignalRWebpack/, per il codice client.

  7. Copiare la src directory e il relativo contenuto dal progetto di esempio nella radice del progetto. La src directory contiene i file seguenti:

    • index.html, che definisce il markup boilerplate della home page:

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="utf-8" />
          <title>ASP.NET Core SignalR with TypeScript and Webpack</title>
        </head>
        <body>
          <div id="divMessages" class="messages"></div>
          <div class="input-zone">
            <label id="lblMessage" for="tbMessage">Message:</label>
            <input id="tbMessage" class="input-zone-input" type="text" />
            <button id="btnSend">Send</button>
          </div>
        </body>
      </html>
      
    • css/main.css, che fornisce stili CSS per la home page:

      *,
      *::before,
      *::after {
        box-sizing: border-box;
      }
      
      html,
      body {
        margin: 0;
        padding: 0;
      }
      
      .input-zone {
        align-items: center;
        display: flex;
        flex-direction: row;
        margin: 10px;
      }
      
      .input-zone-input {
        flex: 1;
        margin-right: 10px;
      }
      
      .message-author {
        font-weight: bold;
      }
      
      .messages {
        border: 1px solid #000;
        margin: 10px;
        max-height: 300px;
        min-height: 300px;
        overflow-y: auto;
        padding: 5px;
      }
      
    • tsconfig.json, che configura il compilatore TypeScript per produrre JavaScript compatibile con ECMAScript 5:

      {
        "compilerOptions": {
          "target": "es5"
        }
      }
      
    • index.ts:

      import * as signalR from "@microsoft/signalr";
      import "./css/main.css";
      
      const divMessages: HTMLDivElement = document.querySelector("#divMessages");
      const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
      const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
      const username = new Date().getTime();
      
      const connection = new signalR.HubConnectionBuilder()
          .withUrl("/hub")
          .build();
      
      connection.on("messageReceived", (username: string, message: string) => {
        const m = document.createElement("div");
      
        m.innerHTML = `<div class="message-author">${username}</div><div>${message}</div>`;
      
        divMessages.appendChild(m);
        divMessages.scrollTop = divMessages.scrollHeight;
      });
      
      connection.start().catch((err) => document.write(err));
      
      tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.key === "Enter") {
          send();
        }
      });
      
      btnSend.addEventListener("click", send);
      
      function send() {
        connection.send("newMessage", username, tbMessage.value)
          .then(() => (tbMessage.value = ""));
      }
      

      Il codice precedente recupera i riferimenti agli elementi DOM e associa due gestori eventi:

      • keyup: viene attivato quando l'utente digita nella tbMessage casella di testo e chiama la send funzione quando l'utente preme il tasto INVIO .
      • click: viene attivato quando l'utente seleziona il pulsante Invia e chiama send la funzione .

      La classe HubConnectionBuilder crea un nuovo compilatore per la configurazione della connessione al server. La funzione withUrl configura l'URL dell'hub.

      SignalR consente lo scambio di messaggi tra un client e un server. Ogni messaggio ha un nome specifico. Ad esempio, i messaggi con il nome messageReceived possono eseguire la logica responsabile della visualizzazione del nuovo messaggio nell'area messaggi. L'ascolto di un messaggio specifico può essere eseguito tramite la funzione on. È possibile restare in ascolto di un numero qualsiasi di nomi di messaggi. Si può anche passare parametri al messaggio, come il nome dell'autore e il contenuto del messaggio ricevuto. Quando il client riceve un messaggio, viene creato un nuovo elemento div con il nome dell'autore e il contenuto del messaggio nell'attributo innerHTML. Viene aggiunto all'elemento div principale che visualizza i messaggi.

      Per inviare un messaggio attraverso la connessione WebSockets è necessario chiamare il metodo send. Il primo parametro del metodo è il nome del messaggio. I dati del messaggio sono rappresentati dagli altri parametri. In questo esempio un messaggio identificato come newMessage viene inviato al server. Il messaggio è costituito dal nome utente e dall'input dell'utente in una casella di testo. Se l'invio riesce, il valore della casella di testo viene cancellato.

  8. Eseguire il comando seguente nella radice del progetto:

    npm i @microsoft/signalr @types/node
    

    Il comando precedente installa:

    • Client SignalR TypeScript, che consente al client di inviare messaggi al server.
    • Le definizioni dei tipi TypeScript per Node.js, che consentono il controllo in fase di compilazione dei tipi Node.js.

Testare l'app

Verificare che l'app funzioni con la procedura seguente:

  1. Eseguire Webpack in release modalità . Usando la finestra della console di Gestione pacchetti, eseguire il comando seguente nella radice del progetto.

    npm run release
    

    Questo comando genera gli asset sul lato client da gestire durante l'esecuzione dell'app. Gli asset vengono inseriti nella wwwroot cartella .

    Webpack ha completato le attività seguenti:

    • Ripulito il contenuto della wwwroot directory.
    • Convertito TypeScript in JavaScript in un processo noto come transpilazione.
    • Mangled javaScript generato per ridurre le dimensioni dei file in un processo noto come minification.
    • Copiati i file JavaScript, CSS e HTML elaborati da src alla wwwroot directory.
    • Inserire gli elementi seguenti nel wwwroot/index.html file:
      • Tag <link> che fa riferimento al wwwroot/main.<hash>.css file. Questo tag viene inserito immediatamente prima del tag </head> di chiusura.
      • Tag <script> che fa riferimento al file minimizzato wwwroot/main.<hash>.js . Questo tag viene inserito immediatamente dopo il tag di chiusura </title> .
  2. Selezionare Debug>Avvia senza eseguire il debug per avviare l'app in un browser senza collegare il debugger. Il wwwroot/index.html file viene gestito in https://localhost:<port>.

    Se sono presenti errori di compilazione, provare a chiudere e riaprire la soluzione.

  3. Aprire un'altra istanza di un browser qualsiasi e incollare l'URL nella barra dell'indirizzo.

  4. Scegliere uno dei browser, digitare qualcosa nella casella di testo Messaggio e selezionare il pulsante Invia . Il nome utente e il messaggio univoci vengono visualizzati immediatamente in entrambe le pagine.

Messaggio visualizzato in entrambe le finestre del browser

Passaggi successivi

Risorse aggiuntive

Questa esercitazione illustra l'uso di Webpack in un'app Web ASP.NET Core SignalR per aggregare e compilare un client scritto in TypeScript. Webpack consente agli sviluppatori di creare un bundle delle risorse di un'app Web sul lato client-e di compilarle.

In questa esercitazione apprenderai a:

  • Creare un'app ASP.NET Core SignalR
  • Configurare il SignalR server
  • Configurare una pipeline di compilazione tramite Webpack
  • Configurare il SignalR client TypeScript
  • Abilitare la comunicazione tra il client e il server

Visualizzare o scaricare il codice di esempio (procedura per il download)

Prerequisiti

Creare l'app Web ASP.NET Core

Per impostazione predefinita, Visual Studio usa la versione di npm trovata nella directory di installazione. Per configurare Visual Studio per cercare npm nella PATH variabile di ambiente:

Avviare Visual Studio. Nella finestra iniziale selezionare Continua senza codice.

  1. Passare a Strumenti>Opzioni>Progetti e soluzioni>Gestione pacchetti Web>Strumenti Web esterni.

  2. Selezionare la $(PATH) voce dall'elenco. Selezionare la freccia su per spostare la voce nella seconda posizione nell'elenco e selezionare OK:

    Configurazione di Visual Studio.

Per creare una nuova app Web ASP.NET Core:

  1. Usare l'opzione di menu File>nuovo>progetto e scegliere il modello ASP.NET core vuoto. Selezionare Avanti.
  2. Assegnare al progetto SignalRWebpackil nome e selezionare Crea.
  3. Selezionare .NET 7.0 (Standard Term Support) dall'elenco a discesa Framework . Seleziona Crea.

Aggiungere il pacchetto NuGet Microsoft.TypeScript.MSBuild al progetto:

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Gestisci pacchetti NuGet. Nella scheda Sfoglia cercare Microsoft.TypeScript.MSBuild e quindi selezionare Installa a destra per installare il pacchetto.

Visual Studio aggiunge il pacchetto NuGet nel nodo Dipendenze in Esplora soluzioni, abilitando la compilazione TypeScript nel progetto.

Configurare il server

In questa sezione viene configurata l'app Web ASP.NET Core per inviare e ricevere SignalR messaggi.

  1. In Program.cschiamare AddSignalR:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddSignalR();
    
  2. Anche in Program.cs, chiamare UseDefaultFiles e UseStaticFiles:

    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    

    Il codice precedente consente al server di individuare e gestire il index.html file. Il file viene gestito indipendentemente dal fatto che l'utente immetta l'URL completo o l'URL radice dell'app Web.

  3. Creare una nuova directory denominata Hubs nella radice del progetto, SignalRWebpack/, per la SignalR classe hub.

  4. Creare un nuovo file, Hubs/ChatHub.cs, con il codice seguente:

    using Microsoft.AspNetCore.SignalR;
    
    namespace SignalRWebpack.Hubs;
    
    public class ChatHub : Hub
    {
        public async Task NewMessage(long username, string message) =>
            await Clients.All.SendAsync("messageReceived", username, message);
    }
    

    Il codice precedente trasmette i messaggi ricevuti a tutti gli utenti connessi dopo che il server li riceve. Non è necessario avere un metodo generico on per ricevere tutti i messaggi. Un metodo denominato dopo il nome del messaggio è sufficiente.

    In questo esempio:

    • Il client TypeScript invia un messaggio identificato come newMessage.
    • Il metodo C# NewMessage si aspetta i dati inviati dal client.
    • Viene effettuata una chiamata a SendAsync su Clients.All.
    • I messaggi ricevuti vengono inviati a tutti i client connessi all'hub.
  5. Aggiungere l'istruzione seguente using all'inizio di Program.cs per risolvere il ChatHub riferimento:

    using SignalRWebpack.Hubs;
    
  6. In Program.cseseguire il mapping della /hub route all'hub ChatHub . Sostituire il codice visualizzato Hello World! con il codice seguente:

    app.MapHub<ChatHub>("/hub");
    

Configurare il client

In questa sezione viene creato un progetto Node.js per convertire TypeScript in JavaScript e aggregare le risorse lato client, incluso HTML e CSS, usando Webpack.

  1. Eseguire il comando seguente nella radice del progetto per creare un package.json file:

    npm init -y
    
  2. Aggiungere la proprietà evidenziata al package.json file e salvare le modifiche apportate al file:

    {
      "name": "SignalRWebpack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Impostando la proprietà private su true si evita la visualizzazione di avvisi di installazione del pacchetto nel passaggio successivo.

  3. Installare i pacchetti npm necessari. Eseguire il comando seguente dalla radice del progetto:

    npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
    

    L'opzione -E disabilita il comportamento predefinito di npm per la scrittura di operatori di intervallo di controllo delle versioni semantici in package.json. Ad esempio, viene usato "webpack": "5.76.1" invece di "webpack": "^5.76.1". Questa opzione impedisce che vengano eseguiti aggiornamenti non desiderati a versioni più recenti del pacchetto.

    Per altre informazioni, vedere la documentazione di npm-install .

  4. Sostituire la scripts proprietà del package.json file con il codice seguente:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Vengono definiti gli script seguenti:

    • build: raggruppa le risorse lato client in modalità di sviluppo e controlla le modifiche dei file. Questo controllo fa sì che il bundle venga rigenerato a ogni modifica del file di progetto. L'opzione mode disabilita le ottimizzazioni di produzione, come l'eliminazione del codice non utilizzato e la minimizzazione. uso build solo in fase di sviluppo.
    • release: raggruppa le risorse lato client in modalità di produzione.
    • publish: esegue lo script release per creare il bundle delle risorse sul lato client in modalità di produzione. Chiama il comando publish dell'interfaccia della riga di comando di .NET per pubblicare l'app.
  5. Creare un file denominato webpack.config.js nella radice del progetto con il codice seguente:

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const { CleanWebpackPlugin } = require("clean-webpack-plugin");
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    module.exports = {
        entry: "./src/index.ts",
        output: {
            path: path.resolve(__dirname, "wwwroot"),
            filename: "[name].[chunkhash].js",
            publicPath: "/",
        },
        resolve: {
            extensions: [".js", ".ts"],
        },
        module: {
            rules: [
                {
                    test: /\.ts$/,
                    use: "ts-loader",
                },
                {
                    test: /\.css$/,
                    use: [MiniCssExtractPlugin.loader, "css-loader"],
                },
            ],
        },
        plugins: [
            new CleanWebpackPlugin(),
            new HtmlWebpackPlugin({
                template: "./src/index.html",
            }),
            new MiniCssExtractPlugin({
                filename: "css/[name].[chunkhash].css",
            }),
        ],
    };
    

    Il file precedente configura il processo di compilazione Webpack:

    • La output proprietà esegue l'override del valore predefinito di dist. Il bundle viene invece generato nella wwwroot directory .
    • La resolve.extensions matrice include .js per importare il SignalR client JavaScript.
  6. Copiare la src directory e il relativo contenuto dal progetto di esempio nella radice del progetto. La src directory contiene i file seguenti:

    • index.html, che definisce il markup boilerplate della home page:

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="utf-8" />
          <title>ASP.NET Core SignalR with TypeScript and Webpack</title>
        </head>
        <body>
          <div id="divMessages" class="messages"></div>
          <div class="input-zone">
            <label id="lblMessage" for="tbMessage">Message:</label>
            <input id="tbMessage" class="input-zone-input" type="text" />
            <button id="btnSend">Send</button>
          </div>
        </body>
      </html>
      
    • css/main.css, che fornisce stili CSS per la home page:

      *,
      *::before,
      *::after {
        box-sizing: border-box;
      }
      
      html,
      body {
        margin: 0;
        padding: 0;
      }
      
      .input-zone {
        align-items: center;
        display: flex;
        flex-direction: row;
        margin: 10px;
      }
      
      .input-zone-input {
        flex: 1;
        margin-right: 10px;
      }
      
      .message-author {
        font-weight: bold;
      }
      
      .messages {
        border: 1px solid #000;
        margin: 10px;
        max-height: 300px;
        min-height: 300px;
        overflow-y: auto;
        padding: 5px;
      }
      
    • tsconfig.json, che configura il compilatore TypeScript per produrre JavaScript compatibile con ECMAScript 5:

      {
        "compilerOptions": {
          "target": "es5"
        }
      }
      
    • index.ts:

      import * as signalR from "@microsoft/signalr";
      import "./css/main.css";
      
      const divMessages: HTMLDivElement = document.querySelector("#divMessages");
      const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
      const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
      const username = new Date().getTime();
      
      const connection = new signalR.HubConnectionBuilder()
          .withUrl("/hub")
          .build();
      
      connection.on("messageReceived", (username: string, message: string) => {
        const m = document.createElement("div");
      
        m.innerHTML = `<div class="message-author">${username}</div><div>${message}</div>`;
      
        divMessages.appendChild(m);
        divMessages.scrollTop = divMessages.scrollHeight;
      });
      
      connection.start().catch((err) => document.write(err));
      
      tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.key === "Enter") {
          send();
        }
      });
      
      btnSend.addEventListener("click", send);
      
      function send() {
        connection.send("newMessage", username, tbMessage.value)
          .then(() => (tbMessage.value = ""));
      }
      

      Il codice precedente recupera i riferimenti agli elementi DOM e associa due gestori eventi:

      • keyup: viene attivato quando l'utente digita nella tbMessage casella di testo e chiama la send funzione quando l'utente preme il tasto INVIO .
      • click: viene attivato quando l'utente seleziona il pulsante Invia e chiama send la funzione .

      La classe HubConnectionBuilder crea un nuovo compilatore per la configurazione della connessione al server. La funzione withUrl configura l'URL dell'hub.

      SignalR consente lo scambio di messaggi tra un client e un server. Ogni messaggio ha un nome specifico. Ad esempio, i messaggi con il nome messageReceived possono eseguire la logica responsabile della visualizzazione del nuovo messaggio nell'area messaggi. L'ascolto di un messaggio specifico può essere eseguito tramite la funzione on. È possibile restare in ascolto di un numero qualsiasi di nomi di messaggi. Si può anche passare parametri al messaggio, come il nome dell'autore e il contenuto del messaggio ricevuto. Quando il client riceve un messaggio, viene creato un nuovo elemento div con il nome dell'autore e il contenuto del messaggio nell'attributo innerHTML. Viene aggiunto all'elemento div principale che visualizza i messaggi.

      Per inviare un messaggio attraverso la connessione WebSockets è necessario chiamare il metodo send. Il primo parametro del metodo è il nome del messaggio. I dati del messaggio sono rappresentati dagli altri parametri. In questo esempio un messaggio identificato come newMessage viene inviato al server. Il messaggio è costituito dal nome utente e dall'input dell'utente in una casella di testo. Se l'invio riesce, il valore della casella di testo viene cancellato.

  7. Eseguire il comando seguente nella radice del progetto:

    npm i @microsoft/signalr @types/node
    

    Il comando precedente installa:

    • Client SignalR TypeScript, che consente al client di inviare messaggi al server.
    • Le definizioni dei tipi TypeScript per Node.js, che consentono il controllo in fase di compilazione dei tipi Node.js.

Testare l'app

Verificare che l'app funzioni con la procedura seguente:

  1. Eseguire Webpack in release modalità . Usando la finestra della console di Gestione pacchetti, eseguire il comando seguente nella radice del progetto.

    npm run release
    

    Questo comando genera gli asset sul lato client da gestire durante l'esecuzione dell'app. Gli asset vengono inseriti nella wwwroot cartella .

    Webpack ha completato le attività seguenti:

    • Ripulito il contenuto della wwwroot directory.
    • Convertito TypeScript in JavaScript in un processo noto come transpilazione.
    • Mangled javaScript generato per ridurre le dimensioni dei file in un processo noto come minification.
    • Copiati i file JavaScript, CSS e HTML elaborati da src alla wwwroot directory.
    • Inserire gli elementi seguenti nel wwwroot/index.html file:
      • Tag <link> che fa riferimento al wwwroot/main.<hash>.css file. Questo tag viene inserito immediatamente prima del tag </head> di chiusura.
      • Tag <script> che fa riferimento al file minimizzato wwwroot/main.<hash>.js . Questo tag viene inserito immediatamente dopo il tag di chiusura </title> .
  2. Selezionare Debug>Avvia senza eseguire il debug per avviare l'app in un browser senza collegare il debugger. Il wwwroot/index.html file viene gestito in https://localhost:<port>.

    Se sono presenti errori di compilazione, provare a chiudere e riaprire la soluzione.

  3. Aprire un'altra istanza di un browser qualsiasi e incollare l'URL nella barra dell'indirizzo.

  4. Scegliere uno dei browser, digitare qualcosa nella casella di testo Messaggio e selezionare il pulsante Invia . Il nome utente e il messaggio univoci vengono visualizzati immediatamente in entrambe le pagine.

Messaggio visualizzato in entrambe le finestre del browser

Passaggi successivi

Risorse aggiuntive

Questa esercitazione illustra l'uso di Webpack in un'app Web ASP.NET Core SignalR per aggregare e compilare un client scritto in TypeScript. Webpack consente agli sviluppatori di creare un bundle delle risorse di un'app Web sul lato client-e di compilarle.

In questa esercitazione apprenderai a:

  • Creare un'app ASP.NET Core SignalR
  • Configurare il SignalR server
  • Configurare una pipeline di compilazione tramite Webpack
  • Configurare il SignalR client TypeScript
  • Abilitare la comunicazione tra il client e il server

Visualizzare o scaricare il codice di esempio (procedura per il download)

Prerequisiti

Creare l'app Web ASP.NET Core

Per impostazione predefinita, Visual Studio usa la versione di npm trovata nella directory di installazione. Per configurare Visual Studio per cercare npm nella PATH variabile di ambiente:

  1. Avviare Visual Studio. Nella finestra iniziale selezionare Continua senza codice.

  2. Passare a Strumenti>Opzioni>Progetti e soluzioni>Gestione pacchetti Web>Strumenti Web esterni.

  3. Selezionare la $(PATH) voce dall'elenco. Selezionare la freccia su per spostare la voce nella seconda posizione nell'elenco e selezionare OK:

    Configurazione di Visual Studio.

Per creare una nuova app Web ASP.NET Core:

  1. Usare l'opzione di menu File>nuovo>progetto e scegliere il modello ASP.NET core vuoto. Selezionare Avanti.
  2. Assegnare al progetto SignalRWebpackil nome e selezionare Crea.
  3. Selezionare .NET 6.0 (Long Term Support) dall'elenco a discesa Framework . Seleziona Crea.

Aggiungere il pacchetto NuGet Microsoft.TypeScript.MSBuild al progetto:

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Gestisci pacchetti NuGet. Nella scheda Sfoglia cercare Microsoft.TypeScript.MSBuild e quindi selezionare Installa a destra per installare il pacchetto.

Visual Studio aggiunge il pacchetto NuGet nel nodo Dipendenze in Esplora soluzioni, abilitando la compilazione TypeScript nel progetto.

Configurare il server

In questa sezione viene configurata l'app Web ASP.NET Core per inviare e ricevere SignalR messaggi.

  1. In Program.cschiamare AddSignalR:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddSignalR();
    
  2. Anche in Program.cs, chiamare UseDefaultFiles e UseStaticFiles:

    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    

    Il codice precedente consente al server di individuare e gestire il index.html file. Il file viene gestito indipendentemente dal fatto che l'utente immetta l'URL completo o l'URL radice dell'app Web.

  3. Creare una nuova directory denominata Hubs nella radice del progetto, SignalRWebpack/, per la SignalR classe hub.

  4. Creare un nuovo file, Hubs/ChatHub.cs, con il codice seguente:

    using Microsoft.AspNetCore.SignalR;
    
    namespace SignalRWebpack.Hubs;
    
    public class ChatHub : Hub
    {
        public async Task NewMessage(long username, string message) =>
            await Clients.All.SendAsync("messageReceived", username, message);
    }
    

    Il codice precedente trasmette i messaggi ricevuti a tutti gli utenti connessi dopo che il server li riceve. Non è necessario avere un metodo generico on per ricevere tutti i messaggi. Un metodo denominato dopo il nome del messaggio è sufficiente.

    In questo esempio il client TypeScript invia un messaggio identificato come newMessage. Il metodo C# NewMessage si aspetta i dati inviati dal client. Viene effettuata una chiamata a SendAsync su Clients.All. I messaggi ricevuti vengono inviati a tutti i client connessi all'hub.

  5. Aggiungere l'istruzione seguente using all'inizio di Program.cs per risolvere il ChatHub riferimento:

    using SignalRWebpack.Hubs;
    
  6. In Program.cseseguire il mapping della /hub route all'hub ChatHub . Sostituire il codice visualizzato Hello World! con il codice seguente:

    app.MapHub<ChatHub>("/hub");
    

Configurare il client

In questa sezione viene creato un progetto Node.js per convertire TypeScript in JavaScript e aggregare le risorse lato client, incluso HTML e CSS, usando Webpack.

  1. Eseguire il comando seguente nella radice del progetto per creare un package.json file:

    npm init -y
    
  2. Aggiungere la proprietà evidenziata al package.json file e salvare le modifiche apportate al file:

    {
      "name": "SignalRWebpack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Impostando la proprietà private su true si evita la visualizzazione di avvisi di installazione del pacchetto nel passaggio successivo.

  3. Installare i pacchetti npm necessari. Eseguire il comando seguente dalla radice del progetto:

    npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
    

    L'opzione -E disabilita il comportamento predefinito di npm per la scrittura di operatori di intervallo di controllo delle versioni semantici in package.json. Ad esempio, viene usato "webpack": "5.70.0" invece di "webpack": "^5.70.0". Questa opzione impedisce che vengano eseguiti aggiornamenti non desiderati a versioni più recenti del pacchetto.

    Per altre informazioni, vedere la documentazione di npm-install .

  4. Sostituire la scripts proprietà del package.json file con il codice seguente:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Vengono definiti gli script seguenti:

    • build: raggruppa le risorse lato client in modalità di sviluppo e controlla le modifiche dei file. Questo controllo fa sì che il bundle venga rigenerato a ogni modifica del file di progetto. L'opzione mode disabilita le ottimizzazioni di produzione, come l'eliminazione del codice non utilizzato e la minimizzazione. uso build solo in fase di sviluppo.
    • release: raggruppa le risorse lato client in modalità di produzione.
    • publish: esegue lo script release per creare il bundle delle risorse sul lato client in modalità di produzione. Chiama il comando publish dell'interfaccia della riga di comando di .NET per pubblicare l'app.
  5. Creare un file denominato webpack.config.js nella radice del progetto con il codice seguente:

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const { CleanWebpackPlugin } = require("clean-webpack-plugin");
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    module.exports = {
      entry: "./src/index.ts",
      output: {
        path: path.resolve(__dirname, "wwwroot"),
        filename: "[name].[chunkhash].js",
        publicPath: "/",
      },
      resolve: {
        extensions: [".js", ".ts"],
      },
      module: {
        rules: [
          {
            test: /\.ts$/,
            use: "ts-loader",
          },
          {
            test: /\.css$/,
            use: [MiniCssExtractPlugin.loader, "css-loader"],
          },
        ],
      },
      plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
          template: "./src/index.html",
        }),
        new MiniCssExtractPlugin({
          filename: "css/[name].[chunkhash].css",
        }),
      ],
    };
    

    Il file precedente configura il processo di compilazione Webpack:

    • La output proprietà esegue l'override del valore predefinito di dist. Il bundle viene invece generato nella wwwroot directory .
    • La resolve.extensions matrice include .js per importare il SignalR client JavaScript.
  6. Copiare la src directory e il relativo contenuto dal progetto di esempio nella radice del progetto. La src directory contiene i file seguenti:

    • index.html, che definisce il markup boilerplate della home page:

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="utf-8" />
          <title>ASP.NET Core SignalR with TypeScript and Webpack</title>
        </head>
        <body>
          <div id="divMessages" class="messages"></div>
          <div class="input-zone">
            <label id="lblMessage" for="tbMessage">Message:</label>
            <input id="tbMessage" class="input-zone-input" type="text" />
            <button id="btnSend">Send</button>
          </div>
        </body>
      </html>
      
    • css/main.css, che fornisce stili CSS per la home page:

      *,
      *::before,
      *::after {
        box-sizing: border-box;
      }
      
      html,
      body {
        margin: 0;
        padding: 0;
      }
      
      .input-zone {
        align-items: center;
        display: flex;
        flex-direction: row;
        margin: 10px;
      }
      
      .input-zone-input {
        flex: 1;
        margin-right: 10px;
      }
      
      .message-author {
        font-weight: bold;
      }
      
      .messages {
        border: 1px solid #000;
        margin: 10px;
        max-height: 300px;
        min-height: 300px;
        overflow-y: auto;
        padding: 5px;
      }
      
    • tsconfig.json, che configura il compilatore TypeScript per produrre JavaScript compatibile con ECMAScript 5:

      {
        "compilerOptions": {
          "target": "es5"
        }
      }
      
    • index.ts:

      import * as signalR from "@microsoft/signalr";
      import "./css/main.css";
      
      const divMessages: HTMLDivElement = document.querySelector("#divMessages");
      const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
      const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
      const username = new Date().getTime();
      
      const connection = new signalR.HubConnectionBuilder()
          .withUrl("/hub")
          .build();
      
      connection.on("messageReceived", (username: string, message: string) => {
        const m = document.createElement("div");
      
        m.innerHTML = `<div class="message-author">${username}</div><div>${message}</div>`;
      
        divMessages.appendChild(m);
        divMessages.scrollTop = divMessages.scrollHeight;
      });
      
      connection.start().catch((err) => document.write(err));
      
      tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.key === "Enter") {
          send();
        }
      });
      
      btnSend.addEventListener("click", send);
      
      function send() {
        connection.send("newMessage", username, tbMessage.value)
          .then(() => (tbMessage.value = ""));
      }
      

    Il codice precedente recupera i riferimenti agli elementi DOM e associa due gestori eventi:

    • keyup: viene attivato quando l'utente digita nella tbMessage casella di testo e chiama la send funzione quando l'utente preme il tasto INVIO .
    • click: viene attivato quando l'utente seleziona il pulsante Invia e chiama send la funzione .

    La classe HubConnectionBuilder crea un nuovo compilatore per la configurazione della connessione al server. La funzione withUrl configura l'URL dell'hub.

    SignalR consente lo scambio di messaggi tra un client e un server. Ogni messaggio ha un nome specifico. Ad esempio, i messaggi con il nome messageReceived possono eseguire la logica responsabile della visualizzazione del nuovo messaggio nell'area messaggi. L'ascolto di un messaggio specifico può essere eseguito tramite la funzione on. È possibile restare in ascolto di un numero qualsiasi di nomi di messaggi. Si può anche passare parametri al messaggio, come il nome dell'autore e il contenuto del messaggio ricevuto. Quando il client riceve un messaggio, viene creato un nuovo elemento div con il nome dell'autore e il contenuto del messaggio nell'attributo innerHTML. Viene aggiunto all'elemento div principale che visualizza i messaggi.

    Per inviare un messaggio attraverso la connessione WebSockets è necessario chiamare il metodo send. Il primo parametro del metodo è il nome del messaggio. I dati del messaggio sono rappresentati dagli altri parametri. In questo esempio un messaggio identificato come newMessage viene inviato al server. Il messaggio è costituito dal nome utente e dall'input dell'utente in una casella di testo. Se l'invio riesce, il valore della casella di testo viene cancellato.

  7. Eseguire il comando seguente nella radice del progetto:

    npm i @microsoft/signalr @types/node
    

    Il comando precedente installa:

    • Client SignalR TypeScript, che consente al client di inviare messaggi al server.
    • Le definizioni dei tipi TypeScript per Node.js, che consentono il controllo in fase di compilazione dei tipi Node.js.

Testare l'app

Verificare che l'app funzioni con la procedura seguente:

  1. Eseguire Webpack in release modalità . Usando la finestra della console di Gestione pacchetti, eseguire il comando seguente nella radice del progetto. Se non si è nella radice del progetto, immettere cd SignalRWebpack prima di immettere il comando .

    npm run release
    

    Questo comando genera gli asset sul lato client da gestire durante l'esecuzione dell'app. Gli asset vengono inseriti nella wwwroot cartella .

    Webpack ha completato le attività seguenti:

    • Ripulito il contenuto della wwwroot directory.
    • Convertito TypeScript in JavaScript in un processo noto come transpilazione.
    • Mangled javaScript generato per ridurre le dimensioni dei file in un processo noto come minification.
    • Copiati i file JavaScript, CSS e HTML elaborati da src alla wwwroot directory.
    • Inserire gli elementi seguenti nel wwwroot/index.html file:
      • Tag <link> che fa riferimento al wwwroot/main.<hash>.css file. Questo tag viene inserito immediatamente prima del tag </head> di chiusura.
      • Tag <script> che fa riferimento al file minimizzato wwwroot/main.<hash>.js . Questo tag viene inserito immediatamente dopo il tag di chiusura </title> .
  2. Selezionare Debug>Avvia senza eseguire il debug per avviare l'app in un browser senza collegare il debugger. Il wwwroot/index.html file viene gestito in https://localhost:<port>.

    Se vengono visualizzati errori di compilazione, provare a chiudere e riaprire la soluzione.

  3. Aprire un'altra istanza di un browser qualsiasi e incollare l'URL nella barra dell'indirizzo.

  4. Scegliere uno dei browser, digitare qualcosa nella casella di testo Messaggio e selezionare il pulsante Invia . Il nome utente e il messaggio univoci vengono visualizzati immediatamente in entrambe le pagine.

Messaggio visualizzato in entrambe le finestre del browser

Passaggi successivi

Risorse aggiuntive

Questa esercitazione illustra l'uso di Webpack in un'app Web ASP.NET Core SignalR per aggregare e compilare un client scritto in TypeScript. Webpack consente agli sviluppatori di creare un bundle delle risorse di un'app Web sul lato client-e di compilarle.

In questa esercitazione apprenderai a:

  • Eseguire lo scaffolding di un'app starter ASP.NET Core SignalR
  • Configurare il SignalR client TypeScript
  • Configurare una pipeline di compilazione tramite Webpack
  • Configurare il SignalR server
  • Abilitare la comunicazione tra client e server

Visualizzare o scaricare il codice di esempio (procedura per il download)

Prerequisiti

Creare l'app Web ASP.NET Core

Configurare Visual Studio in modo che cerchi npm nella variabile di ambiente PATH. Per impostazione predefinita, Visual Studio usa la versione di npm trovata nella directory di installazione. Seguire queste istruzioni in Visual Studio:

  1. Avviare Visual Studio. Nella finestra iniziale selezionare Continua senza codice.

  2. Passare a Strumenti>Opzioni>Progetti e soluzioni>Gestione pacchetti Web>Strumenti Web esterni.

  3. Selezionare la voce $(PATH) dall'elenco. Selezionare la freccia su per spostare la voce nella seconda posizione nell'elenco e selezionare OK.

    Configurazione di Visual Studio.

La configurazione di Visual Studio è stata completata.

  1. Selezionare l'opzione di menu File>Nuovo>Progetto e scegliere il modello Applicazione Web ASP.NET Core. Selezionare Avanti.
  2. Assegnare al progetto il nome *SignalRWebPac'' e selezionare Crea.
  3. Selezionare .NET Core dall'elenco a discesa framework di destinazione e selezionare ASP.NET Core 3.1 nell'elenco a discesa del selettore del framework. Selezionare il modello Vuoto e selezionare Crea.

Aggiungere il Microsoft.TypeScript.MSBuild pacchetto al progetto:

  1. In Esplora soluzioni (riquadro destro) fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Gestisci pacchetti NuGet. Nella scheda Sfoglia cercare Microsoft.TypeScript.MSBuilde quindi fare clic su Installa a destra per installare il pacchetto.

Visual Studio aggiunge il pacchetto NuGet nel nodo Dipendenze in Esplora soluzioni, abilitando la compilazione TypeScript nel progetto.

Configurare Webpack e TypeScript

I passaggi seguenti consentono di configurare la conversione da TypeScript a JavaScript e di creare un bundle delle risorse sul lato client.

  1. Eseguire il comando seguente nella radice del progetto per creare un package.json file:

    npm init -y
    
  2. Aggiungere la proprietà evidenziata al package.json file e salvare le modifiche apportate al file:

    {
      "name": "SignalRWebPack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Impostando la proprietà private su true si evita la visualizzazione di avvisi di installazione del pacchetto nel passaggio successivo.

  3. Installare i pacchetti npm necessari. Eseguire il comando seguente dalla radice del progetto:

    npm i -D -E clean-webpack-plugin@3.0.0 css-loader@3.4.2 html-webpack-plugin@3.2.0 mini-css-extract-plugin@0.9.0 ts-loader@6.2.1 typescript@3.7.5 webpack@4.41.5 webpack-cli@3.3.10
    

    Ecco alcuni dettagli del comando da tenere in considerazione:

    • Un numero di versione segue il segno @ per ogni nome di pacchetto. npm installa queste versioni del pacchetto specifiche.
    • L'opzione -E disabilita il comportamento predefinito di npm per la scrittura di operatori di intervallo di controllo delle versioni semantici in *packagejson. Ad esempio, viene usato "webpack": "4.41.5" invece di "webpack": "^4.41.5". Questa opzione impedisce che vengano eseguiti aggiornamenti non desiderati a versioni più recenti del pacchetto.

    Per altre informazioni, vedere la documentazione npm-install .

  4. Sostituire la scripts proprietà del package.json file con il codice seguente:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Ecco una spiegazione degli script:

    • build: raggruppa le risorse lato client in modalità di sviluppo e controlla le modifiche dei file. Questo controllo fa sì che il bundle venga rigenerato a ogni modifica del file di progetto. L'opzione mode disabilita le ottimizzazioni di produzione, come l'eliminazione del codice non utilizzato e la minimizzazione. Usare build solo in modalità di sviluppo.
    • release: raggruppa le risorse lato client in modalità di produzione.
    • publish: esegue lo script release per creare il bundle delle risorse sul lato client in modalità di produzione. Chiama il comando publish dell'interfaccia della riga di comando di .NET Core per pubblicare l'app.
  5. Creare un file denominato webpack.config.js, nella radice del progetto, con il codice seguente:

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const { CleanWebpackPlugin } = require("clean-webpack-plugin");
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    module.exports = {
        entry: "./src/index.ts",
        output: {
            path: path.resolve(__dirname, "wwwroot"),
            filename: "[name].[chunkhash].js",
            publicPath: "/"
        },
        resolve: {
            extensions: [".js", ".ts"]
        },
        module: {
            rules: [
                {
                    test: /\.ts$/,
                    use: "ts-loader"
                },
                {
                    test: /\.css$/,
                    use: [MiniCssExtractPlugin.loader, "css-loader"]
                }
            ]
        },
        plugins: [
            new CleanWebpackPlugin(),
            new HtmlWebpackPlugin({
                template: "./src/index.html"
            }),
            new MiniCssExtractPlugin({
                filename: "css/[name].[chunkhash].css"
            })
        ]
    };
    

    Il file precedente configura la compilazione di Webpack. Ecco alcuni dettagli di configurazione del server da tenere in considerazione:

    • La output proprietà esegue l'override del valore predefinito di dist. Il bundle viene invece generato nella wwwroot directory .
    • La resolve.extensions matrice include .js per importare il SignalR client JavaScript.
  6. Creare una nuova directory src nella radice del progetto per archiviare gli asset lato client del progetto.

  7. Creare src/index.html con il markup seguente.

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>ASP.NET Core SignalR</title>
    </head>
    <body>
        <div id="divMessages" class="messages">
        </div>
        <div class="input-zone">
            <label id="lblMessage" for="tbMessage">Message:</label>
            <input id="tbMessage" class="input-zone-input" type="text" />
            <button id="btnSend">Send</button>
        </div>
    </body>
    </html>
    

    Il codice HTML precedente definisce il markup del boilerplate della home page.

  8. Creare una nuova directory src/css. Lo scopo è archiviare i file del .css progetto.

  9. Creare src/css/main.css con il codice CSS seguente:

    *, *::before, *::after {
        box-sizing: border-box;
    }
    
    html, body {
        margin: 0;
        padding: 0;
    }
    
    .input-zone {
        align-items: center;
        display: flex;
        flex-direction: row;
        margin: 10px;
    }
    
    .input-zone-input {
        flex: 1;
        margin-right: 10px;
    }
    
    .message-author {
        font-weight: bold;
    }
    
    .messages {
        border: 1px solid #000;
        margin: 10px;
        max-height: 300px;
        min-height: 300px;
        overflow-y: auto;
        padding: 5px;
    }
    

    Il file precedente main.css stili l'app.

  10. Creare src/tsconfig.json con il codice ON seguente JS:

    {
      "compilerOptions": {
        "target": "es5"
      }
    }
    

    Il codice precedente configura il compilatore TypeScript in modo da produrre codice JavaScript compatibile con ECMAScript 5.

  11. Creare src/index.ts con il codice seguente:

    import "./css/main.css";
    
    const divMessages: HTMLDivElement = document.querySelector("#divMessages");
    const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
    const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
    const username = new Date().getTime();
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.key === "Enter") {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
    }
    

    Il compilatore TypeScript precedente recupera i riferimenti agli elementi DOM e collega due gestori eventi:

    • keyup: questo evento viene generato quando l'utente digita nella tbMessagecasella di testo. La funzione send viene chiamata quando l'utente preme INVIO.
    • click: questo evento viene generato quando l'utente seleziona il pulsante Invia . Viene chiamata la funzione send.

Configurare l'app

  1. In Startup.Configureaggiungere chiamate a UseDefaultFiles(IApplicationBuilder) e UseStaticFiles(IApplicationBuilder).

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        
        app.UseRouting();
        app.UseDefaultFiles();
        app.UseStaticFiles();
        
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHub<ChatHub>("/hub");
        });
            
    }
    

    Il codice precedente consente al server di individuare e gestire il index.html file. Il file viene gestito indipendentemente dal fatto che l'utente immetta l'URL completo o l'URL radice dell'app Web.

  2. Alla fine di eseguire il mapping di Startup.Configureuna route /hub all'hub ChatHub . Sostituire il codice che visualizza Hello World! con la riga seguente:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/hub");
    });
    
  3. In Startup.ConfigureServiceschiamare AddSignalR.

    services.AddSignalR();
    
  4. Creare una nuova directory denominata Hubs nella radiceSignalR del progetto WebPack/ per archiviare l'hubSignalR.

  5. Creare l'hub Hubs/ChatHub.cs con il codice seguente:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
        }
    }
    
  6. Aggiungere l'istruzione seguente using all'inizio del Startup.cs file per risolvere il ChatHub riferimento:

    using SignalRWebPack.Hubs;
    

Abilitare la comunicazione tra client e server

L'app visualizza attualmente un modulo di base per l'invio di messaggi, ma non è ancora funzionante. Il server è in ascolto di una route specifica, ma non esegue alcuna operazione con i messaggi inviati.

  1. Eseguire il comando seguente nella radice del progetto:

    npm i @microsoft/signalr @types/node
    

    Il comando precedente installa:

    • Client SignalR TypeScript, che consente al client di inviare messaggi al server.
    • Le definizioni dei tipi TypeScript per Node.js, che consentono il controllo in fase di compilazione dei tipi Node.js.
  2. Aggiungere il codice evidenziato al src/index.ts file:

    import "./css/main.css";
    import * as signalR from "@microsoft/signalr";
    
    const divMessages: HTMLDivElement = document.querySelector("#divMessages");
    const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
    const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
    const username = new Date().getTime();
    
    const connection = new signalR.HubConnectionBuilder()
        .withUrl("/hub")
        .build();
    
    connection.on("messageReceived", (username: string, message: string) => {
        let m = document.createElement("div");
    
        m.innerHTML =
            `<div class="message-author">${username}</div><div>${message}</div>`;
    
        divMessages.appendChild(m);
        divMessages.scrollTop = divMessages.scrollHeight;
    });
    
    connection.start().catch(err => document.write(err));
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.key === "Enter") {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
    }
    

    Il codice precedente supporta la ricezione di messaggi dal server. La classe HubConnectionBuilder crea un nuovo compilatore per la configurazione della connessione al server. La funzione withUrl configura l'URL dell'hub.

    SignalR consente lo scambio di messaggi tra un client e un server. Ogni messaggio ha un nome specifico. Ad esempio, i messaggi con il nome messageReceived possono eseguire la logica responsabile della visualizzazione del nuovo messaggio nell'area messaggi. L'ascolto di un messaggio specifico può essere eseguito tramite la funzione on. È possibile restare in ascolto di un numero qualsiasi di nomi di messaggi. Si può anche passare parametri al messaggio, come il nome dell'autore e il contenuto del messaggio ricevuto. Quando il client riceve un messaggio, viene creato un nuovo elemento div con il nome dell'autore e il contenuto del messaggio nell'attributo innerHTML. Viene aggiunto all'elemento div principale che visualizza i messaggi.

  3. Ora che il client può ricevere messaggi, configurarlo anche per l'invio. Aggiungere il codice evidenziato al src/index.ts file:

    import "./css/main.css";
    import * as signalR from "@microsoft/signalr";
    
    const divMessages: HTMLDivElement = document.querySelector("#divMessages");
    const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
    const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
    const username = new Date().getTime();
    
    const connection = new signalR.HubConnectionBuilder()
        .withUrl("/hub")
        .build();
    
    connection.on("messageReceived", (username: string, message: string) => {
        let messages = document.createElement("div");
    
        messages.innerHTML =
            `<div class="message-author">${username}</div><div>${message}</div>`;
    
        divMessages.appendChild(messages);
        divMessages.scrollTop = divMessages.scrollHeight;
    });
    
    connection.start().catch(err => document.write(err));
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.key === "Enter") {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
        connection.send("newMessage", username, tbMessage.value)
            .then(() => tbMessage.value = "");
    }
    

    Per inviare un messaggio attraverso la connessione WebSockets è necessario chiamare il metodo send. Il primo parametro del metodo è il nome del messaggio. I dati del messaggio sono rappresentati dagli altri parametri. In questo esempio un messaggio identificato come newMessage viene inviato al server. Il messaggio è costituito dal nome utente e dall'input dell'utente in una casella di testo. Se l'invio riesce, il valore della casella di testo viene cancellato.

  4. Aggiungere il metodo NewMessage alla classe ChatHub:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
            public async Task NewMessage(long username, string message)
            {
                await Clients.All.SendAsync("messageReceived", username, message);
            }
        }
    }
    

    Il codice precedente trasmette i messaggi ricevuti a tutti gli utenti connessi dopo che il server li riceve. Non è necessario avere un metodo generico on per ricevere tutti i messaggi. È sufficiente un metodo denominato dopo il nome del messaggio.

    In questo esempio il client TypeScript invia un messaggio identificato come newMessage. Il metodo C# NewMessage si aspetta i dati inviati dal client. Viene effettuata una chiamata a SendAsync su Clients.All. I messaggi ricevuti vengono inviati a tutti i client connessi all'hub.

Testare l'app

Per verificare che l'app funzioni, eseguire la procedura seguente.

  1. Eseguire Webpack in modalità versione. Usando la finestra della console di Gestione pacchetti, eseguire il comando seguente nella radice del progetto. Se non si è nella radice del progetto, immettere cd SignalRWebPack prima di immettere il comando .

    npm run release
    

    Questo comando genera gli asset sul lato client da gestire durante l'esecuzione dell'app. Gli asset vengono inseriti nella wwwroot cartella .

    Webpack ha completato le attività seguenti:

    • Ripulito il contenuto della wwwroot directory.
    • Convertito TypeScript in JavaScript in un processo noto come transpilazione.
    • Mangled javaScript generato per ridurre le dimensioni dei file in un processo noto come minification.
    • Copiati i file JavaScript, CSS e HTML elaborati da src alla wwwroot directory.
    • Inserire gli elementi seguenti nel wwwroot/index.html file:
      • Tag <link> che fa riferimento al wwwroot/main.<hash>.css file. Questo tag viene inserito immediatamente prima del tag </head> di chiusura.
      • Tag <script> che fa riferimento al file minimizzato wwwroot/main.<hash>.js . Questo tag viene inserito immediatamente dopo il tag di chiusura </title> .
  2. Selezionare Debug>Avvia senza eseguire il debug per avviare l'app in un browser senza collegare il debugger. Il wwwroot/index.html file viene gestito in http://localhost:<port_number>.

    Se vengono visualizzati errori di compilazione, provare a chiudere e riaprire la soluzione.

  3. Aprire un'altra istanza del browser (qualsiasi browser). Incollare l'URL nella barra degli indirizzi.

  4. Scegliere uno dei browser, digitare qualcosa nella casella di testo Messaggio e selezionare il pulsante Invia . Il nome utente e il messaggio univoci vengono visualizzati immediatamente in entrambe le pagine.

Messaggio visualizzato in entrambe le finestre del browser

Risorse aggiuntive

Questa esercitazione illustra l'uso di Webpack in un'app Web ASP.NET Core SignalR per aggregare e compilare un client scritto in TypeScript. Webpack consente agli sviluppatori di creare un bundle delle risorse di un'app Web sul lato client-e di compilarle.

In questa esercitazione apprenderai a:

  • Eseguire lo scaffolding di un'app starter ASP.NET Core SignalR
  • Configurare il SignalR client TypeScript
  • Configurare una pipeline di compilazione tramite Webpack
  • Configurare il SignalR server
  • Abilitare la comunicazione tra client e server

Visualizzare o scaricare il codice di esempio (procedura per il download)

Prerequisiti

Creare l'app Web ASP.NET Core

Configurare Visual Studio in modo che cerchi npm nella variabile di ambiente PATH. Per impostazione predefinita, Visual Studio usa la versione di npm trovata nella directory di installazione. Seguire queste istruzioni in Visual Studio:

  1. Passare a Strumenti>Opzioni>Progetti e soluzioni>Gestione pacchetti Web>Strumenti Web esterni.

  2. Selezionare la voce $(PATH) dall'elenco. Selezionare la freccia su per spostare la voce nella seconda posizione nell'elenco.

    Configurazione di Visual Studio

La configurazione di Visual Studio è completata. A questo punto è possibile creare il progetto

  1. Selezionare l'opzione di menu File>Nuovo>Progetto e scegliere il modello Applicazione Web ASP.NET Core.
  2. Assegnare al progetto il nome *SignalRWebPack' e selezionare Crea.
  3. Selezionare .NET Core nell'elenco a discesa del framework di destinazione e quindi selezionare ASP.NET Core 2.2 nell'elenco a discesa del selettore del framework. Selezionare il modello Vuoto e selezionare Crea.

Configurare Webpack e TypeScript

I passaggi seguenti consentono di configurare la conversione da TypeScript a JavaScript e di creare un bundle delle risorse sul lato client.

  1. Eseguire il comando seguente nella radice del progetto per creare un package.json file:

    npm init -y
    
  2. Aggiungere la proprietà evidenziata al package.json file:

    {
      "name": "SignalRWebPack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Impostando la proprietà private su true si evita la visualizzazione di avvisi di installazione del pacchetto nel passaggio successivo.

  3. Installare i pacchetti npm necessari. Eseguire il comando seguente dalla radice del progetto:

    npm install -D -E clean-webpack-plugin@1.0.1 css-loader@2.1.0 html-webpack-plugin@4.0.0-beta.5 mini-css-extract-plugin@0.5.0 ts-loader@5.3.3 typescript@3.3.3 webpack@4.29.3 webpack-cli@3.2.3
    

    Ecco alcuni dettagli del comando da tenere in considerazione:

    • Un numero di versione segue il segno @ per ogni nome di pacchetto. npm installa queste versioni del pacchetto specifiche.
    • L'opzione -E disabilita il comportamento predefinito di npm per la scrittura di operatori di intervallo di controllo delle versioni semantici in *packagejson. Ad esempio, viene usato "webpack": "4.29.3" invece di "webpack": "^4.29.3". Questa opzione impedisce che vengano eseguiti aggiornamenti non desiderati a versioni più recenti del pacchetto.

    Per altre informazioni, vedere la documentazione npm-install .

  4. Sostituire la scripts proprietà del package.json file con il codice seguente:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Ecco una spiegazione degli script:

    • build: raggruppa le risorse lato client in modalità di sviluppo e controlla le modifiche dei file. Questo controllo fa sì che il bundle venga rigenerato a ogni modifica del file di progetto. L'opzione mode disabilita le ottimizzazioni di produzione, come l'eliminazione del codice non utilizzato e la minimizzazione. Usare build solo in modalità di sviluppo.
    • release: raggruppa le risorse lato client in modalità di produzione.
    • publish: esegue lo script release per creare il bundle delle risorse sul lato client in modalità di produzione. Chiama il comando publish dell'interfaccia della riga di comando di .NET Core per pubblicare l'app.
  5. Creare un file denominato*webpack.config.js nella radice del progetto con il codice seguente:

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const CleanWebpackPlugin = require("clean-webpack-plugin");
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    module.exports = {
        entry: "./src/index.ts",
        output: {
            path: path.resolve(__dirname, "wwwroot"),
            filename: "[name].[chunkhash].js",
            publicPath: "/"
        },
        resolve: {
            extensions: [".js", ".ts"]
        },
        module: {
            rules: [
                {
                    test: /\.ts$/,
                    use: "ts-loader"
                },
                {
                    test: /\.css$/,
                    use: [MiniCssExtractPlugin.loader, "css-loader"]
                }
            ]
        },
        plugins: [
            new CleanWebpackPlugin(["wwwroot/*"]),
            new HtmlWebpackPlugin({
                template: "./src/index.html"
            }),
            new MiniCssExtractPlugin({
                filename: "css/[name].[chunkhash].css"
            })
        ]
    };
    

    Il file precedente configura la compilazione di Webpack. Ecco alcuni dettagli di configurazione del server da tenere in considerazione:

    • La output proprietà esegue l'override del valore predefinito di dist. Il bundle viene invece generato nella wwwroot directory .
    • La resolve.extensions matrice include .js per importare il SignalR client JavaScript.
  6. Creare una nuova directory src nella radice del progetto per archiviare gli asset lato client del progetto.

  7. Creare src/index.html con il markup seguente.

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>ASP.NET Core SignalR</title>
    </head>
    <body>
        <div id="divMessages" class="messages">
        </div>
        <div class="input-zone">
            <label id="lblMessage" for="tbMessage">Message:</label>
            <input id="tbMessage" class="input-zone-input" type="text" />
            <button id="btnSend">Send</button>
        </div>
    </body>
    </html>
    

    Il codice HTML precedente definisce il markup del boilerplate della home page.

  8. Creare una nuova directory src/css. Lo scopo è archiviare i file del .css progetto.

  9. Creare src/css/main.css con il markup seguente:

    *, *::before, *::after {
        box-sizing: border-box;
    }
    
    html, body {
        margin: 0;
        padding: 0;
    }
    
    .input-zone {
        align-items: center;
        display: flex;
        flex-direction: row;
        margin: 10px;
    }
    
    .input-zone-input {
        flex: 1;
        margin-right: 10px;
    }
    
    .message-author {
        font-weight: bold;
    }
    
    .messages {
        border: 1px solid #000;
        margin: 10px;
        max-height: 300px;
        min-height: 300px;
        overflow-y: auto;
        padding: 5px;
    }
    

    Il file precedente main.css stili l'app.

  10. Creare src/tsconfig.json con il codice ON seguente JS:

    {
      "compilerOptions": {
        "target": "es5"
      }
    }
    

    Il codice precedente configura il compilatore TypeScript in modo da produrre codice JavaScript compatibile con ECMAScript 5.

  11. Creare src/index.ts con il codice seguente:

    import "./css/main.css";
    
    const divMessages: HTMLDivElement = document.querySelector("#divMessages");
    const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
    const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
    const username = new Date().getTime();
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.keyCode === 13) {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
    }
    

    Il compilatore TypeScript precedente recupera i riferimenti agli elementi DOM e collega due gestori eventi:

    • keyup: questo evento viene generato quando l'utente digita nella tbMessage casella di testo. La funzione send viene chiamata quando l'utente preme INVIO.
    • click: questo evento viene generato quando l'utente seleziona il pulsante Invia . Viene chiamata la funzione send.

Configurare l'app ASP.NET Core

  1. Il codice fornito nel metodo Startup.Configure visualizza Hello World!. Sostituire la chiamata al app.Run metodo con chiamate a UseDefaultFiles(IApplicationBuilder) e UseStaticFiles(IApplicationBuilder).

    app.UseDefaultFiles();
    app.UseStaticFiles();
    

    Il codice precedente consente al server di individuare e gestire il index.html file, indipendentemente dal fatto che l'utente immetta l'URL completo o l'URL radice dell'app Web.

  2. Chiamare AddSignalR in Startup.ConfigureServices. Aggiunge i SignalR servizi al progetto.

    services.AddSignalR();
    
  3. Eseguire il mapping di una route /hub all'hub ChatHub. Aggiungere le righe seguenti alla fine di Startup.Configure:

    app.UseSignalR(options =>
    {
        options.MapHub<ChatHub>("/hub");
    });
    
  4. Creare una nuova directory denominata Hubs nella radice del progetto. Lo scopo è archiviare l'hub SignalR , creato nel passaggio successivo.

  5. Creare l'hub Hubs/ChatHub.cs con il codice seguente:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
        }
    }
    
  6. Aggiungere il codice seguente all'inizio del Startup.cs file per risolvere il ChatHub riferimento:

    using SignalRWebPack.Hubs;
    

Abilitare la comunicazione tra client e server

L'app attualmente visualizza un semplice form per l'invio di messaggi. Quando si prova a eseguire questa operazione, non accade nulla. Il server è in ascolto di una route specifica, ma non esegue alcuna operazione con i messaggi inviati.

  1. Eseguire il comando seguente nella radice del progetto:

    npm install @aspnet/signalr
    

    Il comando precedente installa il SignalR client TypeScript, che consente al client di inviare messaggi al server.

  2. Aggiungere il codice evidenziato al src/index.ts file:

    import "./css/main.css";
    import * as signalR from "@aspnet/signalr";
    
    const divMessages: HTMLDivElement = document.querySelector("#divMessages");
    const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
    const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
    const username = new Date().getTime();
    
    const connection = new signalR.HubConnectionBuilder()
        .withUrl("/hub")
        .build();
    
    connection.on("messageReceived", (username: string, message: string) => {
        let m = document.createElement("div");
    
        m.innerHTML =
            `<div class="message-author">${username}</div><div>${message}</div>`;
    
        divMessages.appendChild(m);
        divMessages.scrollTop = divMessages.scrollHeight;
    });
    
    connection.start().catch(err => document.write(err));
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.keyCode === 13) {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
    }
    

    Il codice precedente supporta la ricezione di messaggi dal server. La classe HubConnectionBuilder crea un nuovo compilatore per la configurazione della connessione al server. La funzione withUrl configura l'URL dell'hub.

    SignalR consente lo scambio di messaggi tra un client e un server. Ogni messaggio ha un nome specifico. Ad esempio, i messaggi con il nome messageReceived possono eseguire la logica responsabile della visualizzazione del nuovo messaggio nell'area messaggi. L'ascolto di un messaggio specifico può essere eseguito tramite la funzione on. È possibile restare in ascolto di un numero indefinito di nomi di messaggio. Si può anche passare parametri al messaggio, come il nome dell'autore e il contenuto del messaggio ricevuto. Quando il client riceve un messaggio, viene creato un nuovo elemento div con il nome dell'autore e il contenuto del messaggio nell'attributo innerHTML. Il nuovo messaggio viene aggiunto all'elemento principale div che visualizza i messaggi.

  3. Ora che il client può ricevere messaggi, configurarlo anche per l'invio. Aggiungere il codice evidenziato al src/index.ts file:

    import "./css/main.css";
    import * as signalR from "@aspnet/signalr";
    
    const divMessages: HTMLDivElement = document.querySelector("#divMessages");
    const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
    const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
    const username = new Date().getTime();
    
    const connection = new signalR.HubConnectionBuilder()
        .withUrl("/hub")
        .build();
    
    connection.on("messageReceived", (username: string, message: string) => {
        let messageContainer = document.createElement("div");
    
        messageContainer.innerHTML =
            `<div class="message-author">${username}</div><div>${message}</div>`;
    
        divMessages.appendChild(messageContainer);
        divMessages.scrollTop = divMessages.scrollHeight;
    });
    
    connection.start().catch(err => document.write(err));
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.keyCode === 13) {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
        connection.send("newMessage", username, tbMessage.value)
                  .then(() => tbMessage.value = "");
    }
    

    Per inviare un messaggio attraverso la connessione WebSockets è necessario chiamare il metodo send. Il primo parametro del metodo è il nome del messaggio. I dati del messaggio sono rappresentati dagli altri parametri. In questo esempio un messaggio identificato come newMessage viene inviato al server. Il messaggio è costituito dal nome utente e dall'input dell'utente in una casella di testo. Se l'invio riesce, il valore della casella di testo viene cancellato.

  4. Aggiungere il metodo NewMessage alla classe ChatHub:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
            public async Task NewMessage(long username, string message)
            {
                await Clients.All.SendAsync("messageReceived", username, message);
            }
        }
    }
    

    Il codice precedente trasmette i messaggi ricevuti a tutti gli utenti connessi dopo che il server li riceve. Non è necessario avere un metodo generico on per ricevere tutti i messaggi. È sufficiente un metodo denominato dopo il nome del messaggio.

    In questo esempio il client TypeScript invia un messaggio identificato come newMessage. Il metodo C# NewMessage si aspetta i dati inviati dal client. Viene effettuata una chiamata a SendAsync su Clients.All. I messaggi ricevuti vengono inviati a tutti i client connessi all'hub.

Testare l'app

Per verificare che l'app funzioni, eseguire la procedura seguente.

  1. Eseguire Webpack in modalità versione. Usando la finestra della console di Gestione pacchetti, eseguire il comando seguente nella radice del progetto. Se non si è nella radice del progetto, immettere cd SignalRWebPack prima di immettere il comando .

    npm run release
    

    Questo comando genera gli asset sul lato client da gestire durante l'esecuzione dell'app. Gli asset vengono inseriti nella wwwroot cartella .

    Webpack ha completato le attività seguenti:

    • Ripulito il contenuto della wwwroot directory.
    • Convertito TypeScript in JavaScript in un processo noto come transpilazione.
    • Mangled javaScript generato per ridurre le dimensioni dei file in un processo noto come minification.
    • Copiati i file JavaScript, CSS e HTML elaborati da src alla wwwroot directory.
    • Inserire gli elementi seguenti nel wwwroot/index.html file:
      • Tag <link> che fa riferimento al wwwroot/main.<hash>.css file. Questo tag viene inserito immediatamente prima del tag </head> di chiusura.
      • Tag <script> che fa riferimento al file minimizzato wwwroot/main.<hash>.js . Questo tag viene inserito immediatamente dopo il tag di chiusura </title> .
  2. Selezionare Debug>Avvia senza eseguire il debug per avviare l'app in un browser senza collegare il debugger. Il wwwroot/index.html file viene gestito in http://localhost:<port_number>.

  3. Aprire un'altra istanza del browser (qualsiasi browser). Incollare l'URL nella barra degli indirizzi.

  4. Scegliere uno dei browser, digitare qualcosa nella casella di testo Messaggio e selezionare il pulsante Invia . Il nome utente e il messaggio univoci vengono visualizzati immediatamente in entrambe le pagine.

Messaggio visualizzato in entrambe le finestre del browser

Risorse aggiuntive