Tutorial: Erste Schritte mit ASP.NET Core SignalR mit TypeScript und Webpack

Von Sébastien Sougnez und Scott Addie

In diesem Tutorial wird veranschaulicht, wie Webpack in einer ASP.NET Core SignalR-Web-App verwendet wird, um einen in TypeScript geschriebenen Client zu bündeln und zu erstellen. Mit Webpack können Entwickler clientseitige Ressourcen einer Web-App bündeln und erstellen.

In diesem Tutorial lernen Sie Folgendes:

  • Erstellen einer ASP.NET Core SignalR-App
  • Konfigurieren des SignalR-Servers
  • Konfigurieren einer Buildpipeline mithilfe von Webpack
  • Konfigurieren des SignalR-TypeScript-Clients
  • Herstellen der Kommunikation zwischen dem Client und dem Server

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Voraussetzungen

Erstellen einer ASP.NET Core-Web-App

Visual Studio verwendet standardmäßig die Version von NPM, die sich im Installationsverzeichnis befindet. So konfigurieren Sie Visual Studio, damit in der Umgebungsvariablen PATH nach npm gesucht wird:

  1. Starten Sie Visual Studio. Wählen Sie im Startfenster die Option Ohne Code fortfahren aus.

  2. Navigieren Sie zu Extras>Optionen>Projekte und Projektmappen>Webpaketverwaltung>Externe Webtools.

  3. Wählen Sie in der Liste den Eintrag $(PATH) aus. Drücken Sie die NACH-OBEN-TASTE, um den Eintrag auf die zweite Position in der Liste zu verschieben, und wählen Sie OK aus:

    Visual Studio Configuration

So erstellen Sie eine neue ASP.NET Core-Web-App:

  1. Verwenden Sie die Menüoption Datei>Neu>Projekt, und wählen Sie die Vorlage ASP.NET Core (leer) aus. Klicken Sie auf Weiter.
  2. Geben Sie dem Projekt den Namen SignalRWebpack, und wählen Sie Erstellen aus.
  3. Wählen Sie .NET 6.0 (Long-term support) aus dem Dropdownmenü Framework aus. Klicken Sie auf Erstellen.

Fügen Sie das NuGet-Paket Microsoft.TypeScript.MSBuild zum Projekt hinzu:

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektknoten, und wählen Sie NuGet-Pakete verwalten aus. Suchen Sie auf der Registerkarte Durchsuchen nach Microsoft.TypeScript.MSBuild, und wählen Sie dann rechts Installieren aus, um das Paket zu installieren.

Visual Studio fügt das NuGet-Paket unter dem Knoten Abhängigkeiten im Projektmappen-Explorer hinzu, wodurch die TypeScript-Kompilierung im Projekt aktiviert wird.

Konfigurieren des Servers

In diesem Abschnitt konfigurieren Sie die ASP.NET Core-Web-App zum Senden und Empfangen von SignalR-Nachrichten.

  1. Rufen Sie AddSignalR in Program.cs auf:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddSignalR();
    
  2. Rufen Sie in Program.cs nun UseDefaultFiles und UseStaticFiles auf:

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

    Der vorherige Code ermöglicht dem Server, die index.html-Datei zu finden und bereitzustellen. Die Datei wird bereitgestellt, wenn der Benutzer die vollständige URL oder nur die Stamm-URL der Web-App eingibt.

  3. Erstellen Sie im Projektstamm Hubs ein neues Verzeichnis namens SignalRWebpack/ für die SignalR-Hubklasse.

  4. Erstellen Sie die neue Datei Hubs/ChatHub.cs mit dem folgenden Code:

    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);
    }
    

    Der vorangehende Code überträgt die empfangenen Nachrichten an alle verbundenen Benutzer, sobald der Server sie empfängt. Es ist nicht notwendig, eine generische on-Methode zum Empfangen aller Nachrichten zu verwenden. Eine Methode mit dem gleichen Namen wie die Nachricht genügt.

    In diesem Beispiel sendet der TypeScript-Client eine Nachricht, die als newMessage erkannt wurde. Die C#-Methode NewMessage erwartet die vom Client gesendeten Daten. Es erfolgt ein Aufruf an SendAsync für Clients.All. Die empfangenen Nachrichten werden an alle mit dem Hub verbundenen Clients gesendet.

  5. Fügen Sie die folgende using-Anweisung am Anfang von Program.cs ein, um den ChatHub-Verweis aufzulösen:

    using SignalRWebpack.Hubs;
    
  6. Ordnen Sie in Program.cs die Route /hub dem Hub ChatHub zu. Ersetzen Sie den Code für Hello World! durch den folgenden Code:

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

Konfigurieren des Clients

In diesem Abschnitt erstellen Sie ein Node.js-Projekt , um TypeScript in JavaScript zu konvertieren und clientseitige Ressourcen, einschließlich HTML und CSS, mithilfe von Webpack zu bündeln.

  1. Führen Sie den folgenden Befehl im Projektstamm aus, um eine package.json-Datei zu erstellen:

    npm init -y
    
  2. Fügen Sie der package.json-Datei die hervorgehobene Eigenschaft hinzu, und speichern Sie die Dateiänderungen:

    {
      "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"
    }
    

    Durch Festlegen der Eigenschaft private auf true werden Warnungen bei der Paketinstallation im nächsten Schritt verhindert.

  3. Installieren Sie die erforderlichen NPM-Pakete. Führen Sie den folgenden Befehl über den Projektstamm aus:

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

    Die Option -E deaktiviert das Standardverhalten von npm, das Bereichsoperatoren für die semantische Versionsverwaltung in die Datei package.json schreibt. Beispielsweise wird "webpack": "5.70.0" anstelle von "webpack": "^5.70.0" verwendet. Diese Option verhindert unbeabsichtigte Upgrades auf neuere Paketversionen.

    Weitere Informationen finden Sie in der Dokumentation zu npm-install.

  4. Ersetzen Sie die scripts-Eigenschaft der Datei package.json durch den folgenden Code:

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

    Die folgenden Skripts sind definiert:

    • build: Bündelt die clientseitigen Ressourcen im Entwicklungsmodus und prüft auf Änderungen an Dateien. Der Dateiwatcher generiert das Bündel jedes Mal neu, wenn eine Änderung an einer Projektdatei vorgenommen wird. Die Option mode deaktiviert Produktionsoptimierungsvorgänge wie das „Tree Shaking“ und die „Minimierung“. Verwenden Sie build nur bei der Entwicklung.
    • release: Bündelt clientseitige Ressourcen im Produktionsmodus
    • publish: Führt das release-Skript aus, um die clientseitigen Ressourcen im Produktionsmodus zu bündeln. Es ruft den publish-Befehl der .NET-CLI auf, um die App zu veröffentlichen.
  5. Erstellen Sie eine Datei namens webpack.config.js im Projektstamm mit dem folgenden Code:

    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",
        }),
      ],
    };
    

    Die vorangehende Datei konfiguriert den Webpack-Kompilierungsvorgang:

    • Die Eigenschaft output überschreibt den Standardwert von dist. Das Bündel wird stattdessen an das Verzeichnis wwwroot ausgegeben.
    • Das resolve.extensions-Array schließt .js ein, um den JavaScript-Code des SignalR-Clients zu importieren.
  6. Kopieren Sie das Verzeichnis src aus dem Beispielprojekt in das Projektstammverzeichnis. Das Verzeichnis src enthält die folgenden Dateien:

    • index.html, die die Markup-Codebausteine für die Homepage definiert:

      <!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, die CSS-Stile für die Homepage bereitstellt:

      *,
      *::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, die den TypeScript-Compiler dafür konfiguriert, JavaScript-Code zu generieren, der mit ECMAScript 5 kompatibel ist:

      {
        "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 = ""));
      }
      

      Der vorangehende Code ruft Verweise auf DOM-Elemente ab und fügt zwei Ereignishandler an:

      • keyup: Wird ausgelöst, wenn der*die Benutzer*in eine Eingabe im Textfeld tbMessage macht. Die Funktion send wird aufgerufen, wenn der*die Benutzer*in die EINGABETASTE drückt.
      • click: Wird ausgelöst, wenn der*die Benutzer*in die Schaltfläche Senden auswählt und die Funktion send aufgerufen wird.

      Die Klasse HubConnectionBuilder erstellt einen neuen Generator für die Konfiguration der Serververbindung. Die Funktion withUrl konfiguriert die Hub-URL.

      Mit SignalR wird der Austausch von Nachrichten zwischen einem Client und einem Server ermöglicht. Jede Nachricht verfügt über einen spezifischen Namen. Beispielsweise können Nachrichten mit dem Namen messageReceived die Logik zum Anzeigen neuer Nachrichten im Nachrichtenbereich ausführen. Mit der on-Funktion kann eine spezifische Nachricht belauscht werden. Sie können auf eine beliebige Anzahl von Nachrichtennamen lauschen. Außerdem können Parameter an die Nachricht übergeben werden, z.B. der Name des Autors und der Inhalt der empfangenen Nachricht. Sobald der Client eine Nachricht empfängt, wird ein neues div-Element mit dem Namen des Autors und dem Inhalt der Nachricht im innerHTML-Attribut erstellt. Es wird dem Hauptelement div hinzugefügt, das die Nachrichten anzeigt.

      Für das Senden einer Nachricht über die WebSockets-Verbindung ist das Aufrufen der Methode send erforderlich. Der erste Parameter der Methode ist der Name der Nachricht. Die Nachrichtendaten befinden sich in den anderen Parametern. In diesem Beispiel wird eine Nachricht, die als newMessage erkannt wird, an den Server gesendet. Die Nachricht besteht aus dem Benutzernamen und der Benutzereingabe eines Textfelds. Wenn das Senden funktioniert hat, wird der Textfeldwert gelöscht.

  7. Führen Sie den folgenden Befehl auf der Ebene des Projektstamms aus:

    npm i @microsoft/signalr @types/node
    

    Mit dem vorangestellten Komma wird Folgendes installiert:

    • Der SignalR-TypeScript-Client, mit dem der Client Nachrichten an den Server senden kann.
    • Die TypeScript-Typdefinitionen für Node.js, die die Überprüfung zur Kompilierzeit von Node.js-Typen ermöglichen

Testen der App

Mit den folgenden Schritten können Sie überprüfen, ob die App funktioniert:

  1. Führen Sie Webpack im release aus. Führen Sie im Fenster Paket-Manager-Konsole den folgenden Befehl im Projektstammverzeichnis aus. Wenn Sie sich nicht im Projektstammverzeichnis befinden, geben Sie cd SignalRWebpack ein, bevor Sie den Befehl eingeben.

    npm run release
    

    Dieser Befehl generiert die clientseitigen Objekte an, die bereitgestellt werden, wenn die App ausgeführt wird. Die Objekte werden im Ordner wwwroot gespeichert.

    Webpack hat die folgenden Aufgaben durchgeführt:

    • Die Inhalte des Verzeichnis wwwroot wurden bereinigt.
    • TypeScript wurde in JavaScript konvertiert. Dieser Prozess ist als Transpilierung bekannt.
    • Der generierte JavaScript-Code wurde gekürzt, um die Dateigröße zu reduzieren. Dieser Prozess ist als Minimierung bekannt.
    • Die verarbeiteten JavaScript-, CSS- und HTML-Dateien wurden aus src in das Verzeichnis wwwroot kopiert.
    • Die folgenden Elemente wurden in die Datei wwwroot/index.html eingefügt:
      • Ein <link>-Tag, das auf die wwwroot/main.<hash>.css-Datei verweist Dieses Tag wird unmittelbar vor dem schließenden Tag </head> platziert.
      • Ein <script>-Tag, das auf die verkleinerte wwwroot/main.<hash>.js-Datei verweist Dieses Tag wird unmittelbar vor dem schließenden Tag </body> platziert.
  2. Klicken Sie auf Debuggen>Starten ohne Debugging, um die App in einem Browser zu starten, ohne den Debugger anzufügen. Die Datei wwwroot/index.html wird unter https://localhost:<port> bereitgestellt.

    Wenn Sie Kompilierungsfehlermeldungen erhalten, versuchen Sie, die Projektmappe zu schließen und erneut zu öffnen.

  3. Öffnen Sie eine andere Instanz eines beliebigen Browsers, und fügen Sie die URL in die Adressleiste ein.

  4. Wählen Sie einen beliebigen Browser aus, geben Sie etwas im Textfeld Nachricht ein, und wählen Sie Senden aus. Der eindeutige Benutzername und die Nachricht werden sofort auf beiden Seiten angezeigt.

message displayed in both browser windows

Zusätzliche Ressourcen

In diesem Tutorial wird veranschaulicht, wie Webpack in einer ASP.NET Core SignalR-Web-App verwendet wird, um einen in TypeScript geschriebenen Client zu bündeln und zu erstellen. Mit Webpack können Entwickler clientseitige Ressourcen einer Web-App bündeln und erstellen.

In diesem Tutorial lernen Sie, wie die folgenden Aufgaben ausgeführt werden:

  • Aufbauen einer einfachen ASP.NET Core SignalR-App
  • Konfigurieren des SignalR-TypeScript-Clients
  • Konfigurieren einer Buildpipeline mithilfe von Webpack
  • Konfigurieren des SignalR-Servers
  • Aktivieren der Kommunikation zwischen Client und Server

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Voraussetzungen

Erstellen einer ASP.NET Core-Web-App

Konfigurieren Sie Visual Studio, damit in der Umgebungsvariable PATH nach NPM gesucht wird. Visual Studio verwendet standardmäßig die Version von NPM, die sich im Installationsverzeichnis befindet. Führen Sie die folgenden Anweisungen in Visual Studio aus:

  1. Starten Sie Visual Studio. Wählen Sie im Startfenster die Option Ohne Code fortfahren aus.

  2. Navigieren Sie zu Extras>Optionen>Projekte und Projektmappen>Webpaketverwaltung>Externe Webtools.

  3. Wählen Sie in der Liste den Eintrag $(PATH) aus. Drücken Sie die NACH-OBEN-TASTE, um den Eintrag auf die zweite Position in der Liste zu verschieben, und wählen Sie OK aus.

    Visual Studio Configuration

Die Konfiguration von Visual Studio ist abgeschlossen.

  1. Verwenden Sie die Menüoption Datei>Neu>Projekt, und wählen Sie die Vorlage ASP.NET Core-Web-App aus. Klicken Sie auf Weiter.
  2. Benennen Sie das Projekt *SignalRWebPac``, und wählen Sie Erstellen aus.
  3. Wählen Sie in der Dropdownliste mit Zielframeworks .NET Core und in der Dropdownliste zur Auswahl des Frameworks ASP.NET Core 3.1 aus. Wählen Sie die leere Vorlage und dann Erstellen aus.

Microsoft.TypeScript.MSBuild-Paket zu Projekt hinzufügen:

  1. Klicken Sie im Projektmappen-Explorer (rechter Bereich) mit der rechten Maustaste auf den Projektknoten, und wählen Sie NuGet-Pakete verwalten aus. Suchen Sie auf der Registerkarte Durchsuchen nach Microsoft.TypeScript.MSBuild, und klicken Sie dann rechts auf Installieren, um das Paket zu installieren.

Visual Studio fügt das NuGet-Paket unter dem Knoten Abhängigkeiten im Projektmappen-Explorer hinzu, wodurch die TypeScript-Kompilierung im Projekt aktiviert wird.

Konfigurieren von Webpack und TypeScript

In den folgenden Schritten wird die Konvertierung von TypeScript zu JavaScript und die Bündelung clientseitiger Ressourcen konfiguriert.

  1. Führen Sie den folgenden Befehl im Projektstamm aus, um eine package.json-Datei zu erstellen:

    npm init -y
    
  2. Fügen Sie der package.json-Datei die hervorgehobene Eigenschaft hinzu, und speichern Sie die Dateiänderungen:

    {
      "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"
    }
    

    Durch Festlegen der Eigenschaft private auf true werden Warnungen bei der Paketinstallation im nächsten Schritt verhindert.

  3. Installieren Sie die erforderlichen NPM-Pakete. Führen Sie den folgenden Befehl über den Projektstamm aus:

    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
    

    Beachten Sie folgende Informationen:

    • Auf das @-Zeichen folgt bei jedem Paketnamen eine Versionsnummer. Die spezifischen Paketversionen werden von NPM installiert.
    • Die Option -E deaktiviert das Standardverhalten von npm, das Bereichsoperatoren für die semantische Versionierung in die Datei „*packagejson“ schreibt. Beispielsweise wird "webpack": "4.41.5" anstelle von "webpack": "^4.41.5" verwendet. Diese Option verhindert unbeabsichtigte Upgrades auf neuere Paketversionen.

    Ausführliche Informationen finden Sie in der Dokumentation zu npm-install.

  4. Ersetzen Sie die scripts-Eigenschaft der Datei package.json durch den folgenden Code:

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

    Im Folgenden werden die Skripts erklärt:

    • build: Bündelt die clientseitigen Ressourcen im Entwicklungsmodus und prüft auf Änderungen an Dateien. Der Dateiwatcher generiert das Bündel jedes Mal neu, wenn eine Änderung an einer Projektdatei vorgenommen wird. Die Option mode deaktiviert Produktionsoptimierungsvorgänge wie das „Tree Shaking“ und die „Minimierung“. Verwenden Sie build nur in der Entwicklung.
    • release: Bündelt clientseitige Ressourcen im Produktionsmodus
    • publish: Führt das release-Skript aus, um die clientseitigen Ressourcen im Produktionsmodus zu bündeln. Es ruft den publish-Befehl der .NET Core-CLI auf, um die App zu veröffentlichen.
  5. Erstellen Sie eine Datei namens webpack.config.js im Projektstamm mit dem folgenden Code:

    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"
            })
        ]
    };
    

    Die vorangehende Datei konfiguriert die Webpack-Kompilierung. Zu beachtende Konfigurationsdetails:

    • Die Eigenschaft output überschreibt den Standardwert von dist. Das Bündel wird stattdessen an das Verzeichnis wwwroot ausgegeben.
    • Das resolve.extensions-Array schließt .js ein, um den JavaScript-Code des SignalR-Clients zu importieren.
  6. Erstellen Sie ein neues src-Verzeichnis im Projektstamm, um die clientseitigen Ressourcen des Projekts zu speichern.

  7. Erstellen Sie src/index.html mit dem folgenden Markup.

    <!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>
    

    Der vorangehende HTML-Code definiert die Markupbausteine der Homepage.

  8. Erstellen Sie ein neues src/css-Verzeichnis. Es dient als Speicherort für die .css-Dateien des Projekts.

  9. Erstellen Sie src/css/main.css mit der folgenden CSS-Spezifikation:

    *, *::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;
    }
    

    Die vorangehende Datei main.css formatiert die App.

  10. Erstellen Sie src/tsconfig.json mit der folgenden JSON-Spezifikation:

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

    Der vorangehende Code konfiguriert den TypeScript-Compiler, um JavaScript-Code zu erstellen, der mit ECMAScript 5 kompatibel ist.

  11. Erstellen Sie src/index.ts mit dem folgenden Code:

    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() {
    }
    

    Der vorangehende TypeScript-Code ruft Verweise auf DOM-Elemente ab und fügt zwei Ereignishandler an:

    • keyup: Dieses Ereignis wird ausgelöst, wenn der Benutzer etwas in das tbMessage-Textfeld eingibt. Die Funktion send wird aufgerufen, wenn der Benutzer die EINGABETASTE drückt.
    • click: Dieses Ereignis wird ausgelöst, wenn der*die Benutzer*in die Schaltfläche Senden auswählt. Die Funktion send wird aufgerufen.

Konfigurieren der App

  1. Fügen Sie in Startup.Configure Aufrufe von UseDefaultFiles(IApplicationBuilder) und UseStaticFiles(IApplicationBuilder) hinzu.

    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");
        });
            
    }
    

    Der vorherige Code ermöglicht dem Server, die index.html-Datei zu finden und bereitzustellen. Die Datei wird bereitgestellt, wenn der Benutzer die vollständige URL oder nur die Stamm-URL der Web-App eingibt.

  2. Ordnen Sie am Ende von Startup.Configure eine /hub-Route dem ChatHub-Hub zu. Ersetzen Sie den Code, der Hello World! anzeigt, durch die folgende Zeile:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/hub");
    });
    
  3. Rufen Sie AddSignalR in Startup.ConfigureServices auf.

    services.AddSignalR();
    
  4. Erstellen Sie im Projektstamm SignalRWebPack/ ein neues Verzeichnis namens Hubs, um den SignalR-Hub zu speichern.

  5. Erstellen Sie mit dem folgenden Code den Hub Hubs/ChatHub.cs:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
        }
    }
    
  6. Fügen Sie die folgende using-Anweisung am Anfang der Datei Startup.cs ein, um den ChatHub-Verweis aufzulösen:

    using SignalRWebPack.Hubs;
    

Aktivieren der Kommunikation zwischen Client und Server

Die App zeigt zurzeit ein Basisformular zum Senden von Nachrichten an, ist jedoch darüber hinaus nicht funktionsfähig. Der Server lauscht einer spezifischen Route, aber er verarbeitet gesendete Nachrichten nicht.

  1. Führen Sie den folgenden Befehl auf der Ebene des Projektstamms aus:

    npm i @microsoft/signalr @types/node
    

    Mit dem vorangestellten Komma wird Folgendes installiert:

    • Der SignalR-TypeScript-Client, mit dem der Client Nachrichten an den Server senden kann.
    • Die TypeScript-Typdefinitionen für Node.js, die die Überprüfung zur Kompilierzeit von Node.js-Typen ermöglichen
  2. Fügen Sie der Datei src/index.ts den folgenden hervorgehobenen Code hinzu:

    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() {
    }
    

    Der vorangehende Code unterstützt das Empfangen von Nachrichten vom Server. Die Klasse HubConnectionBuilder erstellt einen neuen Generator für die Konfiguration der Serververbindung. Die Funktion withUrl konfiguriert die Hub-URL.

    Mit SignalR wird der Austausch von Nachrichten zwischen einem Client und einem Server ermöglicht. Jede Nachricht verfügt über einen spezifischen Namen. Beispielsweise können Nachrichten mit dem Namen messageReceived die Logik zum Anzeigen neuer Nachrichten im Nachrichtenbereich ausführen. Mit der on-Funktion kann eine spezifische Nachricht belauscht werden. Sie können auf eine beliebige Anzahl von Nachrichtennamen lauschen. Außerdem können Parameter an die Nachricht übergeben werden, z.B. der Name des Autors und der Inhalt der empfangenen Nachricht. Sobald der Client eine Nachricht empfängt, wird ein neues div-Element mit dem Namen des Autors und dem Inhalt der Nachricht im innerHTML-Attribut erstellt. Es wird dem Hauptelement div hinzugefügt, das die Nachrichten anzeigt.

  3. Da der Client nun dazu in der Lage ist, Nachrichten zu empfangen, konfigurieren Sie ihn zum Senden von Nachrichten. Fügen Sie der Datei src/index.ts den folgenden hervorgehobenen Code hinzu:

    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 = "");
    }
    

    Für das Senden einer Nachricht über die WebSockets-Verbindung ist das Aufrufen der Methode send erforderlich. Der erste Parameter der Methode ist der Name der Nachricht. Die Nachrichtendaten befinden sich in den anderen Parametern. In diesem Beispiel wird eine Nachricht, die als newMessage erkannt wird, an den Server gesendet. Die Nachricht besteht aus dem Benutzernamen und der Benutzereingabe eines Textfelds. Wenn das Senden funktioniert hat, wird der Textfeldwert gelöscht.

  4. Fügen Sie der Klasse ChatHub die Methode NewMessage hinzu:

    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);
            }
        }
    }
    

    Der vorangehende Code überträgt die empfangenen Nachrichten an alle verbundenen Benutzer, sobald der Server sie empfängt. Es ist nicht notwendig, eine generische on-Methode zum Empfangen aller Nachrichten zu verwenden. Eine Methode mit demselben Namen wie die Nachricht genügt.

    In diesem Beispiel sendet der TypeScript-Client eine Nachricht, die als newMessage erkannt wurde. Die C#-Methode NewMessage erwartet die vom Client gesendeten Daten. Es erfolgt ein Aufruf an SendAsync für Clients.All. Die empfangenen Nachrichten werden an alle mit dem Hub verbundenen Clients gesendet.

Testen der App

Mit den folgenden Schritten können Sie überprüfen, ob die App funktioniert.

  1. Führen Sie Webpack im Releasemodus aus. Führen Sie im Fenster Paket-Manager-Konsole den folgenden Befehl im Projektstammverzeichnis aus. Wenn Sie sich nicht im Projektstammverzeichnis befinden, geben Sie cd SignalRWebPack ein, bevor Sie den Befehl eingeben.

    npm run release
    

    Dieser Befehl generiert die clientseitigen Objekte an, die bereitgestellt werden, wenn die App ausgeführt wird. Die Objekte werden im Ordner wwwroot gespeichert.

    Webpack hat die folgenden Aufgaben durchgeführt:

    • Die Inhalte des Verzeichnis wwwroot wurden bereinigt.
    • TypeScript wurde in JavaScript konvertiert. Dieser Prozess ist als Transpilierung bekannt.
    • Der generierte JavaScript-Code wurde gekürzt, um die Dateigröße zu reduzieren. Dieser Prozess ist als Minimierung bekannt.
    • Die verarbeiteten JavaScript-, CSS- und HTML-Dateien wurden aus src in das Verzeichnis wwwroot kopiert.
    • Die folgenden Elemente wurden in die Datei wwwroot/index.html eingefügt:
      • Ein <link>-Tag, das auf die wwwroot/main.<hash>.css-Datei verweist Dieses Tag wird unmittelbar vor dem schließenden Tag </head> platziert.
      • Ein <script>-Tag, das auf die verkleinerte wwwroot/main.<hash>.js-Datei verweist Dieses Tag wird unmittelbar vor dem schließenden Tag </body> platziert.
  2. Klicken Sie auf Debuggen>Starten ohne Debugging, um die App in einem Browser zu starten, ohne den Debugger anzufügen. Die Datei wwwroot/index.html wird unter http://localhost:<port_number> bereitgestellt.

    Wenn Sie Kompilierungsfehlermeldungen erhalten, versuchen Sie, die Projektmappe zu schließen und erneut zu öffnen.

  3. Öffnen Sie eine weitere Browserinstanz (beliebiger Browser). Fügen Sie die URL in die Adressleiste ein.

  4. Wählen Sie einen beliebigen Browser aus, geben Sie etwas im Textfeld Nachricht ein, und wählen Sie Senden aus. Der eindeutige Benutzername und die Nachricht werden sofort auf beiden Seiten angezeigt.

message displayed in both browser windows

Zusätzliche Ressourcen

In diesem Tutorial wird veranschaulicht, wie Webpack in einer ASP.NET Core SignalR-Web-App verwendet wird, um einen in TypeScript geschriebenen Client zu bündeln und zu erstellen. Mit Webpack können Entwickler clientseitige Ressourcen einer Web-App bündeln und erstellen.

In diesem Tutorial lernen Sie, wie die folgenden Aufgaben ausgeführt werden:

  • Aufbauen einer einfachen ASP.NET Core SignalR-App
  • Konfigurieren des SignalR-TypeScript-Clients
  • Konfigurieren einer Buildpipeline mithilfe von Webpack
  • Konfigurieren des SignalR-Servers
  • Aktivieren der Kommunikation zwischen Client und Server

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Voraussetzungen

Erstellen einer ASP.NET Core-Web-App

Konfigurieren Sie Visual Studio, damit in der Umgebungsvariable PATH nach NPM gesucht wird. Visual Studio verwendet standardmäßig die Version von NPM, die sich im Installationsverzeichnis befindet. Führen Sie die folgenden Anweisungen in Visual Studio aus:

  1. Navigieren Sie zu Extras>Optionen>Projekte und Projektmappen>Webpaketverwaltung>Externe Webtools.

  2. Wählen Sie in der Liste den Eintrag $(PATH) aus. Drücken Sie die NACH-OBEN-TASTE, um den Eintrag auf die zweite Position in der Liste zu verschieben.

    Visual Studio Configuration

Die Konfiguration von Visual Studio ist abgeschlossen. Jetzt ist es an der Zeit, das Projekt zu erstellen.

  1. Verwenden Sie die Menüoption Datei>Neu>Projekt, und wählen Sie die Vorlage ASP.NET Core-Web-App aus.
  2. Benennen Sie das Projekt *SignalRWebPack`, und wählen Sie Erstellen aus.
  3. Wählen Sie in der Dropdownliste mit Zielframeworks .NET Core und in der Dropdownliste zur Auswahl des Frameworks ASP.NET Core 2.2 aus. Wählen Sie die leere Vorlage und dann Erstellen aus.

Konfigurieren von Webpack und TypeScript

In den folgenden Schritten wird die Konvertierung von TypeScript zu JavaScript und die Bündelung clientseitiger Ressourcen konfiguriert.

  1. Führen Sie den folgenden Befehl im Projektstamm aus, um eine package.json-Datei zu erstellen:

    npm init -y
    
  2. Fügen Sie der package.json-Datei die hervorgehobene Eigenschaft hinzu:

    {
      "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"
    }
    

    Durch Festlegen der Eigenschaft private auf true werden Warnungen bei der Paketinstallation im nächsten Schritt verhindert.

  3. Installieren Sie die erforderlichen NPM-Pakete. Führen Sie den folgenden Befehl über den Projektstamm aus:

    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
    

    Beachten Sie folgende Informationen:

    • Auf das @-Zeichen folgt bei jedem Paketnamen eine Versionsnummer. Die spezifischen Paketversionen werden von NPM installiert.
    • Die Option -E deaktiviert das Standardverhalten von npm, das Bereichsoperatoren für die semantische Versionierung in die Datei „*packagejson“ schreibt. Beispielsweise wird "webpack": "4.29.3" anstelle von "webpack": "^4.29.3" verwendet. Diese Option verhindert unbeabsichtigte Upgrades auf neuere Paketversionen.

    Ausführliche Informationen finden Sie in der Dokumentation zu npm-install.

  4. Ersetzen Sie die scripts-Eigenschaft der Datei package.json durch den folgenden Code:

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

    Im Folgenden werden die Skripts erklärt:

    • build: Bündelt die clientseitigen Ressourcen im Entwicklungsmodus und prüft auf Änderungen an Dateien. Der Dateiwatcher generiert das Bündel jedes Mal neu, wenn eine Änderung an einer Projektdatei vorgenommen wird. Die Option mode deaktiviert Produktionsoptimierungsvorgänge wie das „Tree Shaking“ und die „Minimierung“. Verwenden Sie build nur in der Entwicklung.
    • release: Bündelt clientseitige Ressourcen im Produktionsmodus
    • publish: Führt das release-Skript aus, um die clientseitigen Ressourcen im Produktionsmodus zu bündeln. Es ruft den publish-Befehl der .NET Core-CLI auf, um die App zu veröffentlichen.
  5. Erstellen Sie eine Datei namens *webpack.config.js im Projektstamm mit dem folgenden Code:

    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"
            })
        ]
    };
    

    Die vorangehende Datei konfiguriert die Webpack-Kompilierung. Zu beachtende Konfigurationsdetails:

    • Die Eigenschaft output überschreibt den Standardwert von dist. Das Bündel wird stattdessen an das Verzeichnis wwwroot ausgegeben.
    • Das resolve.extensions-Array schließt .js ein, um den JavaScript-Code des SignalR-Clients zu importieren.
  6. Erstellen Sie ein neues src-Verzeichnis im Projektstamm, um die clientseitigen Ressourcen des Projekts zu speichern.

  7. Erstellen Sie src/index.html mit dem folgenden Markup.

    <!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>
    

    Der vorangehende HTML-Code definiert die Markupbausteine der Homepage.

  8. Erstellen Sie ein neues src/css-Verzeichnis. Es dient als Speicherort für die .css-Dateien des Projekts.

  9. Erstellen Sie src/css/main.css mit dem folgenden Markup:

    *, *::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;
    }
    

    Die vorangehende Datei main.css formatiert die App.

  10. Erstellen Sie src/tsconfig.json mit der folgenden JSON-Spezifikation:

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

    Der vorangehende Code konfiguriert den TypeScript-Compiler, um JavaScript-Code zu erstellen, der mit ECMAScript 5 kompatibel ist.

  11. Erstellen Sie src/index.ts mit dem folgenden Code:

    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() {
    }
    

    Der vorangehende TypeScript-Code ruft Verweise auf DOM-Elemente ab und fügt zwei Ereignishandler an:

    • keyup: Dieses Ereignis wird ausgelöst, wenn der Benutzer etwas in das tbMessage-Textfeld eingibt. Die Funktion send wird aufgerufen, wenn der Benutzer die EINGABETASTE drückt.
    • click: Dieses Ereignis wird ausgelöst, wenn der*die Benutzer*in die Schaltfläche Senden auswählt. Die Funktion send wird aufgerufen.

Konfigurieren einer ASP.NET Core-App

  1. Der in der Methode Startup.Configure bereitgestellte Code zeigt Hello World! an. Ersetzen Sie den Aufruf der Methode app.Run durch Aufrufe von UseDefaultFiles(IApplicationBuilder) und UseStaticFiles(IApplicationBuilder).

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

    Mit dem vorangehenden Code wird dem Server ermöglicht, die Datei index.html zu finden und bereitzustellen, unabhängig davon, ob der Benutzer die vollständige URL oder die Stamm-URL der Web-App eingibt.

  2. Rufen Sie Startup.ConfigureServices in AddSignalR auf. Mit ihr werden die SignalR-Dienste in das Projekt eingefügt.

    services.AddSignalR();
    
  3. Ordnen Sie dem ChatHub-Hub eine /hub-Route zu. Fügen Sie die folgenden Zeilen am Ende von Startup.Configure hinzu:

    app.UseSignalR(options =>
    {
        options.MapHub<ChatHub>("/hub");
    });
    
  4. Erstellen Sie ein neues Verzeichnis namens Hubs am Projektstamm. Es dient als Speicherort des SignalR-Hubs, der im nächsten Schritt erstellt wird.

  5. Erstellen Sie mit dem folgenden Code den Hub Hubs/ChatHub.cs:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
        }
    }
    
  6. Fügen Sie den folgenden Code am Anfang der Datei Startup.cs hinzu, um den ChatHub-Verweis aufzulösen:

    using SignalRWebPack.Hubs;
    

Aktivieren der Kommunikation zwischen Client und Server

Derzeit zeigt die App ein einfaches Formular zum Senden von Nachrichten an. Es geschieht jedoch nichts, wenn Sie versuchen, es zu verwenden. Der Server lauscht einer spezifischen Route, aber er verarbeitet gesendete Nachrichten nicht.

  1. Führen Sie den folgenden Befehl auf der Ebene des Projektstamms aus:

    npm install @aspnet/signalr
    

    Der vorangehende Befehl installiert den SignalR-TypeScript-Client, mit dem der Client Nachrichten an den Server senden kann.

  2. Fügen Sie der Datei src/index.ts den folgenden hervorgehobenen Code hinzu:

    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() {
    }
    

    Der vorangehende Code unterstützt das Empfangen von Nachrichten vom Server. Die Klasse HubConnectionBuilder erstellt einen neuen Generator für die Konfiguration der Serververbindung. Die Funktion withUrl konfiguriert die Hub-URL.

    Mit SignalR wird der Austausch von Nachrichten zwischen einem Client und einem Server ermöglicht. Jede Nachricht verfügt über einen spezifischen Namen. Beispielsweise können Nachrichten mit dem Namen messageReceived die Logik zum Anzeigen neuer Nachrichten im Nachrichtenbereich ausführen. Mit der on-Funktion kann eine spezifische Nachricht belauscht werden. Sie können auf eine beliebige Anzahl von Nachrichtennamen lauschen. Außerdem können Parameter an die Nachricht übergeben werden, z.B. der Name des Autors und der Inhalt der empfangenen Nachricht. Sobald der Client eine Nachricht empfängt, wird ein neues div-Element mit dem Namen des Autors und dem Inhalt der Nachricht im innerHTML-Attribut erstellt. Die neue Nachricht wird dem Hauptelement div hinzugefügt, das die Nachrichten anzeigt.

  3. Da der Client nun dazu in der Lage ist, Nachrichten zu empfangen, konfigurieren Sie ihn zum Senden von Nachrichten. Fügen Sie der Datei src/index.ts den folgenden hervorgehobenen Code hinzu:

    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 = "");
    }
    

    Für das Senden einer Nachricht über die WebSockets-Verbindung ist das Aufrufen der Methode send erforderlich. Der erste Parameter der Methode ist der Name der Nachricht. Die Nachrichtendaten befinden sich in den anderen Parametern. In diesem Beispiel wird eine Nachricht, die als newMessage erkannt wird, an den Server gesendet. Die Nachricht besteht aus dem Benutzernamen und der Benutzereingabe eines Textfelds. Wenn das Senden funktioniert hat, wird der Textfeldwert gelöscht.

  4. Fügen Sie der Klasse ChatHub die Methode NewMessage hinzu:

    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);
            }
        }
    }
    

    Der vorangehende Code überträgt die empfangenen Nachrichten an alle verbundenen Benutzer, sobald der Server sie empfängt. Es ist nicht notwendig, eine generische on-Methode zum Empfangen aller Nachrichten zu verwenden. Eine Methode mit demselben Namen wie die Nachricht genügt.

    In diesem Beispiel sendet der TypeScript-Client eine Nachricht, die als newMessage erkannt wurde. Die C#-Methode NewMessage erwartet die vom Client gesendeten Daten. Es erfolgt ein Aufruf an SendAsync für Clients.All. Die empfangenen Nachrichten werden an alle mit dem Hub verbundenen Clients gesendet.

Testen der App

Mit den folgenden Schritten können Sie überprüfen, ob die App funktioniert.

  1. Führen Sie Webpack im Releasemodus aus. Führen Sie im Fenster Paket-Manager-Konsole den folgenden Befehl im Projektstammverzeichnis aus. Wenn Sie sich nicht im Projektstammverzeichnis befinden, geben Sie cd SignalRWebPack ein, bevor Sie den Befehl eingeben.

    npm run release
    

    Dieser Befehl generiert die clientseitigen Objekte an, die bereitgestellt werden, wenn die App ausgeführt wird. Die Objekte werden im Ordner wwwroot gespeichert.

    Webpack hat die folgenden Aufgaben durchgeführt:

    • Die Inhalte des Verzeichnis wwwroot wurden bereinigt.
    • TypeScript wurde in JavaScript konvertiert. Dieser Prozess ist als Transpilierung bekannt.
    • Der generierte JavaScript-Code wurde gekürzt, um die Dateigröße zu reduzieren. Dieser Prozess ist als Minimierung bekannt.
    • Die verarbeiteten JavaScript-, CSS- und HTML-Dateien wurden aus src in das Verzeichnis wwwroot kopiert.
    • Die folgenden Elemente wurden in die Datei wwwroot/index.html eingefügt:
      • Ein <link>-Tag, das auf die wwwroot/main.<hash>.css-Datei verweist Dieses Tag wird unmittelbar vor dem schließenden Tag </head> platziert.
      • Ein <script>-Tag, das auf die verkleinerte wwwroot/main.<hash>.js-Datei verweist Dieses Tag wird unmittelbar vor dem schließenden Tag </body> platziert.
  2. Klicken Sie auf Debuggen>Starten ohne Debugging, um die App in einem Browser zu starten, ohne den Debugger anzufügen. Die Datei wwwroot/index.html wird unter http://localhost:<port_number> bereitgestellt.

  3. Öffnen Sie eine weitere Browserinstanz (beliebiger Browser). Fügen Sie die URL in die Adressleiste ein.

  4. Wählen Sie einen beliebigen Browser aus, geben Sie etwas im Textfeld Nachricht ein, und wählen Sie Senden aus. Der eindeutige Benutzername und die Nachricht werden sofort auf beiden Seiten angezeigt.

message displayed in both browser windows

Zusätzliche Ressourcen