Tutoriel : Bien démarrer avec ASP.NET Core SignalR à l’aide de TypeScript et Webpack
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la Stratégie de prise en charge de .NET et .NET Core. Pour la version actuelle, consultez la version .NET 8 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 8 de cet article.
Ce tutoriel montre comment utiliser Webpack dans une application web ASP.NET Core SignalR pour regrouper et générer un client écrit en TypeScript. Webpack permet aux développeurs de regrouper et générer les ressources côté client d’une application web.
Dans ce tutoriel, vous allez apprendre à :
- Créer une application ASP.NET Core SignalR
- Configurer le serveur SignalR
- Configurer un pipeline de build à l’aide de Webpack
- Configurer le client TypeScript SignalR
- Activer la communication entre le client et le serveur
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Prérequis
Visual Studio 2022 avec la charge de travail Développement web et ASP.NET.
Créer l’application web ASP.NET Core
Par défaut, Visual Studio utilise la version de npm qu’il trouve dans son répertoire d’installation. Pour configurer Visual Studio pour rechercher npm dans la variable d’environnement PATH
:
Lancez Visual Studio. Dans la fenêtre de démarrage, sélectionnez Continuer sans code.
Accédez à Outils>Options>Projets et solutions>Gestion des packages web>Outils web externes.
Sélectionnez l’entrée
$(PATH)
dans la liste. Sélectionnez la flèche vers le haut pour déplacer l’entrée à la deuxième position de la liste, puis sélectionnez OK :.
Pour créer une application web ASP.NET Core :
- Utilisez l’option de menu Fichier>Nouveau>Projet et choisissez le modèle ASP.NET Core Vide. Cliquez sur Suivant.
- Nommez le projet
SignalRWebpack
, puis sélectionnez Créer. - Sélectionnez .NET 8.0 (prise en charge à long terme) dans la liste déroulante Framework. Sélectionnez Créer.
Ajoutez le package NuGet Microsoft.TypeScript.MSBuild au projet :
- Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud du projet, puis sélectionnez Gérer les packages NuGet. Sous l’onglet Parcourir, recherchez
Microsoft.TypeScript.MSBuild
, puis cliquez sur Installer à droite pour installer le package.
Visual Studio ajoute le package NuGet sous le nœud Dépendances dans Explorateur de solutions, ce qui permet la compilation TypeScript dans le projet.
Configurer le serveur
Dans cette section, vous allez configurer l’application web ASP.NET Core pour envoyer et recevoir des messages SignalR.
Dans
Program.cs
, appelez AddSignalR :var builder = WebApplication.CreateBuilder(args); builder.Services.AddSignalR();
Là encore, dans
Program.cs
, appelez UseDefaultFiles et UseStaticFiles :var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles();
Le code précédent permet au serveur de localiser et de servir le fichier
index.html
. Le fichier est servi si l’utilisateur entre son URL complète ou l’URL racine de l’application web.Créez un répertoire nommé
Hubs
dans la racine du projet,SignalRWebpack/
, pour la classe hub SignalR.Créez un fichier,
Hubs/ChatHub.cs
, avec le code suivant :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); }
Le code précédent diffuse les messages reçus à tous les utilisateurs connectés, une fois que le serveur les reçoit. Vous n’avez pas besoin d’appeler une méthode générique
on
pour recevoir tous les messages. Une méthode nommée après le nom du message est suffisante.Dans cet exemple :
- Le client TypeScript envoie un message identifié comme
newMessage
. - La méthode C#
NewMessage
attend les données envoyées par le client. - Un appel est effectué pour SendAsync sur Clients.All.
- Les messages reçus sont envoyés à tous les clients connectés au hub.
- Le client TypeScript envoie un message identifié comme
Ajoutez l’instruction
using
suivante en haut deProgram.cs
pour résoudre la référenceChatHub
:using SignalRWebpack.Hubs;
Dans
Program.cs
, mappez l’itinéraire/hub
au hubChatHub
. Remplacez le code qui afficheHello World!
par le code suivant :app.MapHub<ChatHub>("/hub");
Configurer le client
Dans cette section, vous allez créer un projet Node.js pour convertir TypeScript en JavaScript et regrouper des ressources côté client, notamment HTML et CSS, à l’aide de Webpack.
Exécutez la commande suivante dans la racine du projet pour créer un fichier
package.json
:npm init -y
Ajoutez la propriété mise en surbrillance au fichier
package.json
et enregistrez les modifications apportées au fichier :{ "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" }
La définition de la propriété
private
surtrue
empêche les avertissements d’installation de package à l’étape suivante.Installez les packages npm nécessaires. À partir de la racine du projet, exécutez la commande suivante :
npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
L’option
-E
désactive le comportement par défaut de npm pour écrire contrôle de version sémantique opérateurs de plage pourpackage.json
. Par exemple,"webpack": "5.76.1"
peut être utilisé à la place de"webpack": "^5.76.1"
. Cette option empêche les mises à niveau involontaires vers des versions de package plus récentes.Pour plus d’informations, consultez la documentation npm-install.
Remplacez la propriété
scripts
du fichierpackage.json
par le code suivant :"scripts": { "build": "webpack --mode=development --watch", "release": "webpack --mode=production", "publish": "npm run release && dotnet publish -c Release" },
Les scripts suivants sont définis :
build
: Regroupe les ressources côté client en mode de développement et surveille les changements de fichier. L’observateur de fichiers force la regénération du regroupement chaque fois qu’un fichier projet change. L’optionmode
désactive les optimisations de production, comme la minimisation de l’arborescence (tree shaking). utilisezbuild
uniquement dans le développement.release
: Regroupe les ressources côté client en mode de production.publish
: Exécute le scriptrelease
pour regrouper les ressources côté client en mode de production. La commande appelle la commande publish de CLI .NET pour publier l’application.
Créez un fichier nommé
webpack.config.js
à la racine du projet avec le code suivant :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", }), ], };
Le fichier précédent configure le processus de compilation Webpack :
- La propriété
output
remplace la valeur par défaut dedist
. Le regroupement est émis dans le répertoirewwwroot
à la place. - Le tableau
resolve.extensions
inclut.js
pour importer le code JavaScript du client SignalR.
- La propriété
Créez un nouveau répertoire nommé
src
à la racine du projet,SignalRWebpack/
, pour le code client.Copiez le répertoire
src
et son contenu de l'exemple de projet vers la racine du projet. Le répertoiresrc
contient les fichiers suivants :index.html
, qui définit le balisage réutilisable de la page d’accueil :<!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
, qui fournit des styles CSS pour la page d’accueil :*, *::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
, qui configure le compilateur TypeScript pour produire javaScript compatible 5 ECMAScript :{ "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 = "")); }
Le code précédent récupère les références aux éléments DOM et attache deux gestionnaires d’événements :
keyup
: se déclenche lorsque l’utilisateur tape dans la zone de textetbMessage
et appelle la fonctionsend
lorsque l’utilisateur appuie sur la touche Entrée.click
: se déclenche lorsque l’utilisateur sélectionne le bouton Envoyer et appellesend
la fonction.
La classe
HubConnectionBuilder
crée un générateur pour configurer la connexion de serveur. La fonctionwithUrl
configure l’URL du hub.SignalR permet l’échange de messages entre un client et un serveur. Chaque message a un nom spécifique. Par exemple, les messages portant le nom
messageReceived
peuvent exécuter la logique responsable de l’affichage du nouveau message dans la zone de messages. L’écoute d’un message spécifique peut être effectuée au moyen de la fonctionon
. N’importe quel nombre de noms de messages peuvent être écoutés. Vous pouvez aussi passer des paramètres au message, comme le nom de l’auteur et le contenu du message reçu. Dès que le client reçoit un message, un élémentdiv
est créé avec le nom de l’auteur et le contenu du message dans son attributinnerHTML
. Il est ajouté à l’élémentdiv
principal qui affiche les messages.L’envoi d’un message au moyen de la connexion WebSocket nécessite l’appel de la méthode
send
. Le premier paramètre de la méthode est le nom du message. Les données du message se trouvent dans les autres paramètres. Dans cet exemple, un message identifié commenewMessage
est envoyé au serveur. Le message se compose du nom d’utilisateur et de l’entrée de l’utilisateur dans une zone de texte. Si l’envoi fonctionne, la valeur de la zone de texte est effacée.
Exécutez la commande suivante à la racine du projet :
npm i @microsoft/signalr @types/node
La commande précédente active :
- Le SignalRclient TypeScript, ce qui permet au client d’envoyer des messages au serveur.
- Définitions de type TypeScript pour Node.js, qui permet la vérification au moment de la compilation des types Node.js.
Test de l'application
Vérifiez que l’application fonctionne avec les étapes suivantes :
Exécutez Webpack en mode
release
. Dans la fenêtre Console du Gestionnaire de package, exécutez la commande suivante à la racine du projet.npm run release
Cette commande génère les ressources côté client à délivrer pendant l’exécution de l’application. Les ressources sont placées dans le dossier
wwwroot
.Webpack a effectué les tâches suivantes :
- Vide le contenu du répertoire
wwwroot
. - Converti le TypeScript en JavaScript dans un processus appelé transpilation.
- Troncation du code JavaScript généré pour réduire la taille de fichier dans un processus appelé minimisation.
- Copie des fichiers JavaScript, CSS et HTML traités à partir de
src
dans le répertoirewwwroot
. - Injection des éléments suivants dans le fichier
wwwroot/index.html
:- Balise
<link>
, référençant le fichierwwwroot/main.<hash>.css
. Cette balise est placée immédiatement avant la balise</head>
de fermeture. - Balise
<script>
, référençant le fichierwwwroot/main.<hash>.js
minifié. Cette balise est placée immédiatement après la balise de fermeture</title>
.
- Balise
- Vide le contenu du répertoire
Sélectionnez Déboguer>Démarrer sans débogage pour lancer l’application dans un navigateur sans attacher le débogueur. Le fichier
wwwroot/index.html
est servi àhttps://localhost:<port>
.En cas d’erreurs de compilation, essayez de fermer et de rouvrir la solution.
Ouvrez une autre instance du navigateur (n’importe quel navigateur) et collez l’URL dans la barre d’adresse.
Choisissez un navigateur, tapez quelque chose dans la zone de texte Message, puis cliquez sur le bouton Envoyer. Le nom unique de l’utilisateur et le message sont affichés instantanément dans les deux pages.
Étapes suivantes
- Hubs fortement typés
- Authentification et autorisation dans ASP.NET Core SignalR
- Protocole Hub MessagePack dans SignalR pour ASP.NET Core
Ressources supplémentaires
Ce tutoriel montre comment utiliser Webpack dans une application web ASP.NET Core SignalR pour regrouper et générer un client écrit en TypeScript. Webpack permet aux développeurs de regrouper et générer les ressources côté client d’une application web.
Dans ce tutoriel, vous allez apprendre à :
- Créer une application ASP.NET Core SignalR
- Configurer le serveur SignalR
- Configurer un pipeline de build à l’aide de Webpack
- Configurer le client TypeScript SignalR
- Activer la communication entre le client et le serveur
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Prérequis
Visual Studio 2022 avec la charge de travail Développement web et ASP.NET.
Créer l’application web ASP.NET Core
Par défaut, Visual Studio utilise la version de npm qu’il trouve dans son répertoire d’installation. Pour configurer Visual Studio pour rechercher npm dans la variable d’environnement PATH
:
Lancez Visual Studio. Dans la fenêtre de démarrage, sélectionnez Continuer sans code.
Accédez à Outils>Options>Projets et solutions>Gestion des packages web>Outils web externes.
Sélectionnez l’entrée
$(PATH)
dans la liste. Sélectionnez la flèche vers le haut pour déplacer l’entrée à la deuxième position de la liste, puis sélectionnez OK :.
Pour créer une application web ASP.NET Core :
- Utilisez l’option de menu Fichier>Nouveau>Projet et choisissez le modèle ASP.NET Core Vide. Cliquez sur Suivant.
- Nommez le projet
SignalRWebpack
, puis sélectionnez Créer. - Sélectionnez
.NET 7.0 (Standard Term Support)
dans la liste déroulante Framework. Cliquez sur Créer.
Ajoutez le package NuGet Microsoft.TypeScript.MSBuild au projet :
- Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud du projet, puis sélectionnez Gérer les packages NuGet. Sous l’onglet Parcourir, recherchez
Microsoft.TypeScript.MSBuild
, puis cliquez sur Installer à droite pour installer le package.
Visual Studio ajoute le package NuGet sous le nœud Dépendances dans Explorateur de solutions, ce qui permet la compilation TypeScript dans le projet.
Configurer le serveur
Dans cette section, vous allez configurer l’application web ASP.NET Core pour envoyer et recevoir des messages SignalR.
Dans
Program.cs
, appelez AddSignalR :var builder = WebApplication.CreateBuilder(args); builder.Services.AddSignalR();
Là encore, dans
Program.cs
, appelez UseDefaultFiles et UseStaticFiles :var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles();
Le code précédent permet au serveur de localiser et de servir le fichier
index.html
. Le fichier est servi si l’utilisateur entre son URL complète ou l’URL racine de l’application web.Créez un répertoire nommé
Hubs
dans la racine du projet,SignalRWebpack/
, pour la classe hub SignalR.Créez un fichier,
Hubs/ChatHub.cs
, avec le code suivant :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); }
Le code précédent diffuse les messages reçus à tous les utilisateurs connectés, une fois que le serveur les reçoit. Vous n’avez pas besoin d’appeler une méthode générique
on
pour recevoir tous les messages. Une méthode nommée après le nom du message est suffisante.Dans cet exemple :
- Le client TypeScript envoie un message identifié comme
newMessage
. - La méthode C#
NewMessage
attend les données envoyées par le client. - Un appel est effectué pour SendAsync sur Clients.All.
- Les messages reçus sont envoyés à tous les clients connectés au hub.
- Le client TypeScript envoie un message identifié comme
Ajoutez l’instruction
using
suivante en haut deProgram.cs
pour résoudre la référenceChatHub
:using SignalRWebpack.Hubs;
Dans
Program.cs
, mappez l’itinéraire/hub
au hubChatHub
. Remplacez le code qui afficheHello World!
par le code suivant :app.MapHub<ChatHub>("/hub");
Configurer le client
Dans cette section, vous allez créer un projet Node.js pour convertir TypeScript en JavaScript et regrouper des ressources côté client, notamment HTML et CSS, à l’aide de Webpack.
Exécutez la commande suivante dans la racine du projet pour créer un fichier
package.json
:npm init -y
Ajoutez la propriété mise en surbrillance au fichier
package.json
et enregistrez les modifications apportées au fichier :{ "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" }
La définition de la propriété
private
surtrue
empêche les avertissements d’installation de package à l’étape suivante.Installez les packages npm nécessaires. À partir de la racine du projet, exécutez la commande suivante :
npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
L’option
-E
désactive le comportement par défaut de npm pour écrire contrôle de version sémantique opérateurs de plage pourpackage.json
. Par exemple,"webpack": "5.76.1"
peut être utilisé à la place de"webpack": "^5.76.1"
. Cette option empêche les mises à niveau involontaires vers des versions de package plus récentes.Pour plus d’informations, consultez la documentation npm-install.
Remplacez la propriété
scripts
du fichierpackage.json
par le code suivant :"scripts": { "build": "webpack --mode=development --watch", "release": "webpack --mode=production", "publish": "npm run release && dotnet publish -c Release" },
Les scripts suivants sont définis :
build
: Regroupe les ressources côté client en mode de développement et surveille les changements de fichier. L’observateur de fichiers force la regénération du regroupement chaque fois qu’un fichier projet change. L’optionmode
désactive les optimisations de production, comme la minimisation de l’arborescence (tree shaking). utilisezbuild
uniquement dans le développement.release
: Regroupe les ressources côté client en mode de production.publish
: Exécute le scriptrelease
pour regrouper les ressources côté client en mode de production. La commande appelle la commande publish de CLI .NET pour publier l’application.
Créez un fichier nommé
webpack.config.js
à la racine du projet avec le code suivant :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", }), ], };
Le fichier précédent configure le processus de compilation Webpack :
- La propriété
output
remplace la valeur par défaut dedist
. Le regroupement est émis dans le répertoirewwwroot
à la place. - Le tableau
resolve.extensions
inclut.js
pour importer le code JavaScript du client SignalR.
- La propriété
Copiez le répertoire
src
et son contenu de l'exemple de projet vers la racine du projet. Le répertoiresrc
contient les fichiers suivants :index.html
, qui définit le balisage réutilisable de la page d’accueil :<!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
, qui fournit des styles CSS pour la page d’accueil :*, *::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
, qui configure le compilateur TypeScript pour produire javaScript compatible 5 ECMAScript :{ "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 = "")); }
Le code précédent récupère les références aux éléments DOM et attache deux gestionnaires d’événements :
keyup
: se déclenche lorsque l’utilisateur tape dans la zone de textetbMessage
et appelle la fonctionsend
lorsque l’utilisateur appuie sur la touche Entrée.click
: se déclenche lorsque l’utilisateur sélectionne le bouton Envoyer et appellesend
la fonction.
La classe
HubConnectionBuilder
crée un générateur pour configurer la connexion de serveur. La fonctionwithUrl
configure l’URL du hub.SignalR permet l’échange de messages entre un client et un serveur. Chaque message a un nom spécifique. Par exemple, les messages portant le nom
messageReceived
peuvent exécuter la logique responsable de l’affichage du nouveau message dans la zone de messages. L’écoute d’un message spécifique peut être effectuée au moyen de la fonctionon
. N’importe quel nombre de noms de messages peuvent être écoutés. Vous pouvez aussi passer des paramètres au message, comme le nom de l’auteur et le contenu du message reçu. Dès que le client reçoit un message, un élémentdiv
est créé avec le nom de l’auteur et le contenu du message dans son attributinnerHTML
. Il est ajouté à l’élémentdiv
principal qui affiche les messages.L’envoi d’un message au moyen de la connexion WebSocket nécessite l’appel de la méthode
send
. Le premier paramètre de la méthode est le nom du message. Les données du message se trouvent dans les autres paramètres. Dans cet exemple, un message identifié commenewMessage
est envoyé au serveur. Le message se compose du nom d’utilisateur et de l’entrée de l’utilisateur dans une zone de texte. Si l’envoi fonctionne, la valeur de la zone de texte est effacée.
Exécutez la commande suivante à la racine du projet :
npm i @microsoft/signalr @types/node
La commande précédente active :
- Le SignalRclient TypeScript, ce qui permet au client d’envoyer des messages au serveur.
- Définitions de type TypeScript pour Node.js, qui permet la vérification au moment de la compilation des types Node.js.
Test de l'application
Vérifiez que l’application fonctionne avec les étapes suivantes :
Exécutez Webpack en mode
release
. Dans la fenêtre Console du Gestionnaire de package, exécutez la commande suivante à la racine du projet.npm run release
Cette commande génère les ressources côté client à délivrer pendant l’exécution de l’application. Les ressources sont placées dans le dossier
wwwroot
.Webpack a effectué les tâches suivantes :
- Vide le contenu du répertoire
wwwroot
. - Converti le TypeScript en JavaScript dans un processus appelé transpilation.
- Troncation du code JavaScript généré pour réduire la taille de fichier dans un processus appelé minimisation.
- Copie des fichiers JavaScript, CSS et HTML traités à partir de
src
dans le répertoirewwwroot
. - Injection des éléments suivants dans le fichier
wwwroot/index.html
:- Balise
<link>
, référençant le fichierwwwroot/main.<hash>.css
. Cette balise est placée immédiatement avant la balise</head>
de fermeture. - Balise
<script>
, référençant le fichierwwwroot/main.<hash>.js
minifié. Cette balise est placée immédiatement après la balise de fermeture</title>
.
- Balise
- Vide le contenu du répertoire
Sélectionnez Déboguer>Démarrer sans débogage pour lancer l’application dans un navigateur sans attacher le débogueur. Le fichier
wwwroot/index.html
est servi àhttps://localhost:<port>
.En cas d’erreurs de compilation, essayez de fermer et de rouvrir la solution.
Ouvrez une autre instance du navigateur (n’importe quel navigateur) et collez l’URL dans la barre d’adresse.
Choisissez un navigateur, tapez quelque chose dans la zone de texte Message, puis cliquez sur le bouton Envoyer. Le nom unique de l’utilisateur et le message sont affichés instantanément dans les deux pages.
Étapes suivantes
- Hubs fortement typés
- Authentification et autorisation dans ASP.NET Core SignalR
- Protocole Hub MessagePack dans SignalR pour ASP.NET Core
Ressources supplémentaires
Ce tutoriel montre comment utiliser Webpack dans une application web ASP.NET Core SignalR pour regrouper et générer un client écrit en TypeScript. Webpack permet aux développeurs de regrouper et générer les ressources côté client d’une application web.
Dans ce tutoriel, vous allez apprendre à :
- Créer une application ASP.NET Core SignalR
- Configurer le serveur SignalR
- Configurer un pipeline de build à l’aide de Webpack
- Configurer le client TypeScript SignalR
- Activer la communication entre le client et le serveur
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Prérequis
- Visual Studio 2022 avec la charge de travail Développement web et ASP.NET.
- SDK .NET 6.0
Créer l’application web ASP.NET Core
Par défaut, Visual Studio utilise la version de npm qu’il trouve dans son répertoire d’installation. Pour configurer Visual Studio pour rechercher npm dans la variable d’environnement PATH
:
Lancez Visual Studio. Dans la fenêtre de démarrage, sélectionnez Continuer sans code.
Accédez à Outils>Options>Projets et solutions>Gestion des packages web>Outils web externes.
Sélectionnez l’entrée
$(PATH)
dans la liste. Sélectionnez la flèche vers le haut pour déplacer l’entrée à la deuxième position de la liste, puis sélectionnez OK :.
Pour créer une application web ASP.NET Core :
- Utilisez l’option de menu Fichier>Nouveau>Projet et choisissez le modèle ASP.NET Core Vide. Cliquez sur Suivant.
- Nommez le projet
SignalRWebpack
, puis sélectionnez Créer. - Sélectionnez
.NET 6.0 (Long Term Support)
dans la liste déroulante Framework. Cliquez sur Créer.
Ajoutez le package NuGet Microsoft.TypeScript.MSBuild au projet :
- Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud du projet, puis sélectionnez Gérer les packages NuGet. Sous l’onglet Parcourir, recherchez
Microsoft.TypeScript.MSBuild
, puis cliquez sur Installer à droite pour installer le package.
Visual Studio ajoute le package NuGet sous le nœud Dépendances dans Explorateur de solutions, ce qui permet la compilation TypeScript dans le projet.
Configurer le serveur
Dans cette section, vous allez configurer l’application web ASP.NET Core pour envoyer et recevoir des messages SignalR.
Dans
Program.cs
, appelez AddSignalR :var builder = WebApplication.CreateBuilder(args); builder.Services.AddSignalR();
Là encore, dans
Program.cs
, appelez UseDefaultFiles et UseStaticFiles :var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles();
Le code précédent permet au serveur de localiser et de servir le fichier
index.html
. Le fichier est servi si l’utilisateur entre son URL complète ou l’URL racine de l’application web.Créez un répertoire nommé
Hubs
dans la racine du projet,SignalRWebpack/
, pour la classe hub SignalR.Créez un fichier,
Hubs/ChatHub.cs
, avec le code suivant :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); }
Le code précédent diffuse les messages reçus à tous les utilisateurs connectés, une fois que le serveur les reçoit. Vous n’avez pas besoin d’appeler une méthode générique
on
pour recevoir tous les messages. Une méthode nommée après le nom du message est suffisante.Dans cet exemple, le client TypeScript envoie un message identifié comme
newMessage
. La méthode C#NewMessage
attend les données envoyées par le client. Un appel est effectué pour SendAsync sur Clients.All. Les messages reçus sont envoyés à tous les clients connectés au hub.Ajoutez l’instruction
using
suivante en haut deProgram.cs
pour résoudre la référenceChatHub
:using SignalRWebpack.Hubs;
Dans
Program.cs
, mappez l’itinéraire/hub
au hubChatHub
. Remplacez le code qui afficheHello World!
par le code suivant :app.MapHub<ChatHub>("/hub");
Configurer le client
Dans cette section, vous allez créer un projet Node.js pour convertir TypeScript en JavaScript et regrouper des ressources côté client, notamment HTML et CSS, à l’aide de Webpack.
Exécutez la commande suivante dans la racine du projet pour créer un fichier
package.json
:npm init -y
Ajoutez la propriété mise en surbrillance au fichier
package.json
et enregistrez les modifications apportées au fichier :{ "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" }
La définition de la propriété
private
surtrue
empêche les avertissements d’installation de package à l’étape suivante.Installez les packages npm nécessaires. À partir de la racine du projet, exécutez la commande suivante :
npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
L’option
-E
désactive le comportement par défaut de npm pour écrire contrôle de version sémantique opérateurs de plage pourpackage.json
. Par exemple,"webpack": "5.70.0"
peut être utilisé à la place de"webpack": "^5.70.0"
. Cette option empêche les mises à niveau involontaires vers des versions de package plus récentes.Pour plus d’informations, consultez la documentation npm-install.
Remplacez la propriété
scripts
du fichierpackage.json
par le code suivant :"scripts": { "build": "webpack --mode=development --watch", "release": "webpack --mode=production", "publish": "npm run release && dotnet publish -c Release" },
Les scripts suivants sont définis :
build
: Regroupe les ressources côté client en mode de développement et surveille les changements de fichier. L’observateur de fichiers force la regénération du regroupement chaque fois qu’un fichier projet change. L’optionmode
désactive les optimisations de production, comme la minimisation de l’arborescence (tree shaking). utilisezbuild
uniquement dans le développement.release
: Regroupe les ressources côté client en mode de production.publish
: Exécute le scriptrelease
pour regrouper les ressources côté client en mode de production. La commande appelle la commande publish de CLI .NET pour publier l’application.
Créez un fichier nommé
webpack.config.js
à la racine du projet avec le code suivant :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", }), ], };
Le fichier précédent configure le processus de compilation Webpack :
- La propriété
output
remplace la valeur par défaut dedist
. Le regroupement est émis dans le répertoirewwwroot
à la place. - Le tableau
resolve.extensions
inclut.js
pour importer le code JavaScript du client SignalR.
- La propriété
Copiez le répertoire
src
et son contenu de l'exemple de projet vers la racine du projet. Le répertoiresrc
contient les fichiers suivants :index.html
, qui définit le balisage réutilisable de la page d’accueil :<!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
, qui fournit des styles CSS pour la page d’accueil :*, *::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
, qui configure le compilateur TypeScript pour produire javaScript compatible 5 ECMAScript :{ "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 = "")); }
Le code précédent récupère les références aux éléments DOM et attache deux gestionnaires d’événements :
keyup
: se déclenche lorsque l’utilisateur tape dans la zone de textetbMessage
et appelle la fonctionsend
lorsque l’utilisateur appuie sur la touche Entrée.click
: se déclenche lorsque l’utilisateur sélectionne le bouton Envoyer et appellesend
la fonction.
La classe
HubConnectionBuilder
crée un générateur pour configurer la connexion de serveur. La fonctionwithUrl
configure l’URL du hub.SignalR permet l’échange de messages entre un client et un serveur. Chaque message a un nom spécifique. Par exemple, les messages portant le nom
messageReceived
peuvent exécuter la logique responsable de l’affichage du nouveau message dans la zone de messages. L’écoute d’un message spécifique peut être effectuée au moyen de la fonctionon
. N’importe quel nombre de noms de messages peuvent être écoutés. Vous pouvez aussi passer des paramètres au message, comme le nom de l’auteur et le contenu du message reçu. Dès que le client reçoit un message, un élémentdiv
est créé avec le nom de l’auteur et le contenu du message dans son attributinnerHTML
. Il est ajouté à l’élémentdiv
principal qui affiche les messages.L’envoi d’un message au moyen de la connexion WebSocket nécessite l’appel de la méthode
send
. Le premier paramètre de la méthode est le nom du message. Les données du message se trouvent dans les autres paramètres. Dans cet exemple, un message identifié commenewMessage
est envoyé au serveur. Le message se compose du nom d’utilisateur et de l’entrée de l’utilisateur dans une zone de texte. Si l’envoi fonctionne, la valeur de la zone de texte est effacée.Exécutez la commande suivante à la racine du projet :
npm i @microsoft/signalr @types/node
La commande précédente active :
- Le SignalRclient TypeScript, ce qui permet au client d’envoyer des messages au serveur.
- Définitions de type TypeScript pour Node.js, qui permet la vérification au moment de la compilation des types Node.js.
Test de l'application
Vérifiez que l’application fonctionne avec les étapes suivantes :
Exécutez Webpack en mode
release
. Dans la fenêtre Console du Gestionnaire de package, exécutez la commande suivante à la racine du projet. Si vous ne vous trouvez pas à la racine du projet, tapezcd SignalRWebpack
avant d’entrer la commande.npm run release
Cette commande génère les ressources côté client à délivrer pendant l’exécution de l’application. Les ressources sont placées dans le dossier
wwwroot
.Webpack a effectué les tâches suivantes :
- Vide le contenu du répertoire
wwwroot
. - Converti le TypeScript en JavaScript dans un processus appelé transpilation.
- Troncation du code JavaScript généré pour réduire la taille de fichier dans un processus appelé minimisation.
- Copie des fichiers JavaScript, CSS et HTML traités à partir de
src
dans le répertoirewwwroot
. - Injection des éléments suivants dans le fichier
wwwroot/index.html
:- Balise
<link>
, référençant le fichierwwwroot/main.<hash>.css
. Cette balise est placée immédiatement avant la balise</head>
de fermeture. - Balise
<script>
, référençant le fichierwwwroot/main.<hash>.js
minifié. Cette balise est placée immédiatement après la balise de fermeture</title>
.
- Balise
- Vide le contenu du répertoire
Sélectionnez Déboguer>Démarrer sans débogage pour lancer l’application dans un navigateur sans attacher le débogueur. Le fichier
wwwroot/index.html
est servi àhttps://localhost:<port>
.Si vous obtenez des erreurs de compilation, essayez de fermer et de rouvrir la solution.
Ouvrez une autre instance du navigateur (n’importe quel navigateur) et collez l’URL dans la barre d’adresse.
Choisissez un navigateur, tapez quelque chose dans la zone de texte Message, puis cliquez sur le bouton Envoyer. Le nom unique de l’utilisateur et le message sont affichés instantanément dans les deux pages.
Étapes suivantes
- Hubs fortement typés
- Authentification et autorisation dans ASP.NET Core SignalR
- Protocole Hub MessagePack dans SignalR pour ASP.NET Core
Ressources supplémentaires
Ce tutoriel montre comment utiliser Webpack dans une application web ASP.NET Core SignalR pour regrouper et générer un client écrit en TypeScript. Webpack permet aux développeurs de regrouper et générer les ressources côté client d’une application web.
Dans ce tutoriel, vous allez apprendre à :
- Structurer une application de démarrage ASP.NET Core SignalR
- Configurer le client TypeScript SignalR
- Configurer un pipeline de build à l’aide de Webpack
- Configurer le serveur SignalR
- Activer la communication entre le client et le serveur
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Prérequis
- Visual Studio 2019 avec la charge de travail ASP.NET et développement web
- SDK .NET Core 3.0 ou ultérieur
- Node.js avec npm
Créer l’application web ASP.NET Core
Configurez Visual Studio pour rechercher npm dans la variable d'environnement PATH. Par défaut, Visual Studio utilise la version de npm qu’il trouve dans son répertoire d’installation. Suivez ces instructions dans Visual Studio :
Lancez Visual Studio. Dans la fenêtre de démarrage, sélectionnez Continuer sans code.
Accédez à Outils>Options>Projets et solutions>Gestion des packages web>Outils web externes.
Sélectionnez l’entrée $(PATH) dans la liste. Sélectionnez la flèche vers le haut pour déplacer l’entrée à la deuxième position de la liste, puis sélectionnez OK.
.
La configuration de Visual Studio est terminée.
- Utilisez l’option de menu Fichier>Nouveau>Projet et choisissez le modèle Application web ASP.NET Core. Cliquez sur Suivant.
- Nommez le projet *SignalRWebPac``, puis sélectionnez Créer.
- Sélectionnez .NET Core dans la liste déroulante du framework cible, puis ASP.NET Core 3.1 dans la liste déroulante du sélecteur de framework. Sélectionnez le modèle Vide, puis sélectionnez Créer.
Ajoutez le package Microsoft.TypeScript.MSBuild
au projet :
- Dans Explorateur de solutions (panneau droit), cliquez avec le bouton droit sur le nœud du projet, puis sélectionnez Gérer les packages NuGet. Dans l'onglet Parcourir, recherchez
Microsoft.TypeScript.MSBuild
, puis cliquez sur Installer à droite pour installer le package.
Visual Studio ajoute le package NuGet sous le nœud Dépendances dans Explorateur de solutions, ce qui permet la compilation TypeScript dans le projet.
Configurer Webpack et TypeScript
Les étapes suivantes configurent la conversion de TypeScript en JavaScript et le regroupement des ressources côté client.
Exécutez la commande suivante dans la racine du projet pour créer un fichier
package.json
:npm init -y
Ajoutez la propriété mise en surbrillance au fichier
package.json
et enregistrez les modifications apportées au fichier :{ "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" }
La définition de la propriété
private
surtrue
empêche les avertissements d’installation de package à l’étape suivante.Installez les packages npm nécessaires. À partir de la racine du projet, exécutez la commande suivante :
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
Détails de commande à prendre en compte :
- Un numéro de version suit le signe
@
pour chaque nom de package. npm installe ces versions de package spécifiques. - L’option
-E
désactive le comportement par défaut de npm consistant à écrire des opérateurs de plage de gestion sémantique des versions dans packagejson
. Par exemple,"webpack": "4.41.5"
peut être utilisé à la place de"webpack": "^4.41.5"
. Cette option empêche les mises à niveau involontaires vers des versions de package plus récentes.
Consultez la documentation npm-install pour plus de détails.
- Un numéro de version suit le signe
Remplacez la propriété
scripts
du fichierpackage.json
par le code suivant :"scripts": { "build": "webpack --mode=development --watch", "release": "webpack --mode=production", "publish": "npm run release && dotnet publish -c Release" },
Explication des scripts :
build
: Regroupe les ressources côté client en mode de développement et surveille les changements de fichier. L’observateur de fichiers force la regénération du regroupement chaque fois qu’un fichier projet change. L’optionmode
désactive les optimisations de production, comme la minimisation de l’arborescence (tree shaking). Utilisez uniquementbuild
dans le développement.release
: Regroupe les ressources côté client en mode de production.publish
: Exécute le scriptrelease
pour regrouper les ressources côté client en mode de production. La commande appelle la commande publish de CLI .NET pour publier l’application.
Créez un fichier nommé
webpack.config.js
à la racine du projet avec le code suivant :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" }) ] };
Le fichier précédent configure la compilation Webpack. Détails de configuration à prendre en compte :
- La propriété
output
remplace la valeur par défaut dedist
. Le regroupement est émis dans le répertoirewwwroot
à la place. - Le tableau
resolve.extensions
inclut.js
pour importer le code JavaScript du client SignalR.
- La propriété
Créez un répertoire src à la racine du projet pour stocker les ressources côté client du projet.
Créez
src/index.html
avec le balisage suivant.<!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>
Le code HTML précédent définit le balisage réutilisable de la page d’accueil.
Créez un répertoire src/css. Son objectif est de stocker les fichiers
.css
du projet.Créez
src/css/main.css
avec le CSS suivant :*, *::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; }
Le fichier
main.css
précédent définit le style de l’application.Créez
src/tsconfig.json
avec le JSON suivant :{ "compilerOptions": { "target": "es5" } }
Le code précédent configure le compilateur TypeScript pour produire du code JavaScript compatible ECMAScript 5.
Créez
src/index.ts
avec le code suivant :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() { }
Le code TypeScript précédent récupère les références aux éléments DOM et joint deux gestionnaires d’événements :
keyup
: Cet événement se déclenche quand l’utilisateur tape des données dans la zone de textetbMessage
. La fonctionsend
est appelée quand l’utilisateur appuie sur la touche Entrée.click
: Cet événement se déclenche quand l’utilisateur clique sur le bouton Envoyer. La fonctionsend
est appelée.
Configurer l’application
Dans
Startup.Configure
, ajoutez des appels à UseDefaultFiles(IApplicationBuilder) et 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"); }); }
Le code précédent permet au serveur de localiser et de servir le fichier
index.html
. Le fichier est servi si l’utilisateur entre son URL complète ou l’URL racine de l’application web.À la fin de
Startup.Configure
, mappez un itinéraire /hub auChatHub
hub. Remplacez le code qui affiche Hello World! par la ligne suivante :app.UseEndpoints(endpoints => { endpoints.MapHub<ChatHub>("/hub"); });
Dans
Startup.ConfigureServices
, appelez AddSignalR.services.AddSignalR();
Créez un répertoire nommé Hubs dans la racine du projet SignalRWebPack/ pour stocker le hub SignalR.
Créez un hub
Hubs/ChatHub.cs
avec le code suivant :using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace SignalRWebPack.Hubs { public class ChatHub : Hub { } }
Ajoutez l’instruction
using
suivante en haut du fichierStartup.cs
pour résoudre la référenceChatHub
:using SignalRWebPack.Hubs;
Activer la communication entre le client et le serveur
L’application affiche actuellement un formulaire de base pour envoyer des messages, mais n’est pas encore fonctionnelle. Le serveur écoute une route spécifique, mais ne fait rien avec les messages envoyés.
Exécutez la commande suivante à la racine du projet :
npm i @microsoft/signalr @types/node
La commande précédente active :
- Le SignalRclient TypeScript, ce qui permet au client d’envoyer des messages au serveur.
- Définitions de type TypeScript pour Node.js, qui permet la vérification au moment de la compilation des types Node.js.
Ajoutez le code mis en surbrillance au fichier
src/index.ts
: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() { }
Le code précédent prend en charge la réception de messages du serveur. La classe
HubConnectionBuilder
crée un générateur pour configurer la connexion de serveur. La fonctionwithUrl
configure l’URL du hub.SignalR permet l’échange de messages entre un client et un serveur. Chaque message a un nom spécifique. Par exemple, les messages portant le nom
messageReceived
peuvent exécuter la logique responsable de l’affichage du nouveau message dans la zone de messages. L’écoute d’un message spécifique peut être effectuée au moyen de la fonctionon
. N’importe quel nombre de noms de messages peuvent être écoutés. Vous pouvez aussi passer des paramètres au message, comme le nom de l’auteur et le contenu du message reçu. Dès que le client reçoit un message, un élémentdiv
est créé avec le nom de l’auteur et le contenu du message dans son attributinnerHTML
. Il est ajouté à l’élémentdiv
principal qui affiche les messages.Maintenant que le client peut recevoir un message, configurez-le pour en envoyer. Ajoutez le code mis en surbrillance au fichier
src/index.ts
: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 = ""); }
L’envoi d’un message au moyen de la connexion WebSocket nécessite l’appel de la méthode
send
. Le premier paramètre de la méthode est le nom du message. Les données du message se trouvent dans les autres paramètres. Dans cet exemple, un message identifié commenewMessage
est envoyé au serveur. Le message se compose du nom d’utilisateur et de l’entrée de l’utilisateur dans une zone de texte. Si l’envoi fonctionne, la valeur de la zone de texte est effacée.Ajoutez la méthode
NewMessage
à la classeChatHub
: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); } } }
Le code précédent diffuse les messages reçus à tous les utilisateurs connectés, une fois que le serveur les reçoit. Vous n’avez pas besoin d’appeler une méthode générique
on
pour recevoir tous les messages. Il vous suffit d’avoir une méthode du même nom que le message.Dans cet exemple, le client TypeScript envoie un message identifié comme
newMessage
. La méthode C#NewMessage
attend les données envoyées par le client. Un appel est effectué pour SendAsync sur Clients.All. Les messages reçus sont envoyés à tous les clients connectés au hub.
Test de l'application
Vérifiez que l’application fonctionne avec les étapes suivantes.
Exécuter Webpack en mode de mise en production. Dans la fenêtre Console du Gestionnaire de package, exécutez la commande suivante à la racine du projet. Si vous ne vous trouvez pas à la racine du projet, tapez
cd SignalRWebPack
avant d’entrer la commande.npm run release
Cette commande génère les ressources côté client à délivrer pendant l’exécution de l’application. Les ressources sont placées dans le dossier
wwwroot
.Webpack a effectué les tâches suivantes :
- Vide le contenu du répertoire
wwwroot
. - Converti le TypeScript en JavaScript dans un processus appelé transpilation.
- Troncation du code JavaScript généré pour réduire la taille de fichier dans un processus appelé minimisation.
- Copie des fichiers JavaScript, CSS et HTML traités à partir de
src
dans le répertoirewwwroot
. - Injection des éléments suivants dans le fichier
wwwroot/index.html
:- Balise
<link>
, référençant le fichierwwwroot/main.<hash>.css
. Cette balise est placée immédiatement avant la balise</head>
de fermeture. - Balise
<script>
, référençant le fichierwwwroot/main.<hash>.js
minifié. Cette balise est placée immédiatement après la balise de fermeture</title>
.
- Balise
- Vide le contenu du répertoire
Sélectionnez Déboguer>Démarrer sans débogage pour lancer l’application dans un navigateur sans attacher le débogueur. Le fichier
wwwroot/index.html
est servi àhttp://localhost:<port_number>
.Si vous obtenez des erreurs de compilation, essayez de fermer et de rouvrir la solution.
Ouvrez une autre instance de navigateur (n’importe quel navigateur). Copiez l’URL de la barre d’adresse.
Choisissez un navigateur, tapez quelque chose dans la zone de texte Message, puis cliquez sur le bouton Envoyer. Le nom unique de l’utilisateur et le message sont affichés instantanément dans les deux pages.
Ressources supplémentaires
Ce tutoriel montre comment utiliser Webpack dans une application web ASP.NET Core SignalR pour regrouper et générer un client écrit en TypeScript. Webpack permet aux développeurs de regrouper et générer les ressources côté client d’une application web.
Dans ce tutoriel, vous allez apprendre à :
- Structurer une application de démarrage ASP.NET Core SignalR
- Configurer le client TypeScript SignalR
- Configurer un pipeline de build à l’aide de Webpack
- Configurer le serveur SignalR
- Activer la communication entre le client et le serveur
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Prérequis
- Visual Studio 2019 avec la charge de travail ASP.NET et développement web
- Kit SDK .NET Core 2.2 ou version ultérieure
- Node.js avec npm
Créer l’application web ASP.NET Core
Configurez Visual Studio pour rechercher npm dans la variable d'environnement PATH. Par défaut, Visual Studio utilise la version de npm qu’il trouve dans son répertoire d’installation. Suivez ces instructions dans Visual Studio :
Accédez à Outils>Options>Projets et solutions>Gestion des packages web>Outils web externes.
Sélectionnez l’entrée $(PATH) dans la liste. Sélectionnez la flèche vers le haut pour déplacer l’entrée à la deuxième position de la liste.
La configuration de Visual Studio est terminée. Nous allons maintenant créer le projet.
- Utilisez l’option de menu Fichier>Nouveau>Projet et choisissez le modèle Application web ASP.NET Core.
- Nommez le projet *SignalRWebPack`, puis sélectionnez Créer.
- Sélectionnez .NET Core dans la liste déroulante du framework cible, puis ASP.NET Core 2.2 dans la liste déroulante du sélecteur de framework. Sélectionnez le modèle Vide, puis sélectionnez Créer.
Configurer Webpack et TypeScript
Les étapes suivantes configurent la conversion de TypeScript en JavaScript et le regroupement des ressources côté client.
Exécutez la commande suivante dans la racine du projet pour créer un fichier
package.json
:npm init -y
Ajoutez la propriété en surbrillance au fichier
package.json
:{ "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" }
La définition de la propriété
private
surtrue
empêche les avertissements d’installation de package à l’étape suivante.Installez les packages npm nécessaires. À partir de la racine du projet, exécutez la commande suivante :
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
Détails de commande à prendre en compte :
- Un numéro de version suit le signe
@
pour chaque nom de package. npm installe ces versions de package spécifiques. - L’option
-E
désactive le comportement par défaut de npm consistant à écrire des opérateurs de plage de gestion sémantique des versions dans packagejson
. Par exemple,"webpack": "4.29.3"
peut être utilisé à la place de"webpack": "^4.29.3"
. Cette option empêche les mises à niveau involontaires vers des versions de package plus récentes.
Consultez la documentation npm-install pour plus de détails.
- Un numéro de version suit le signe
Remplacez la propriété
scripts
du fichierpackage.json
par le code suivant :"scripts": { "build": "webpack --mode=development --watch", "release": "webpack --mode=production", "publish": "npm run release && dotnet publish -c Release" },
Explication des scripts :
build
: Regroupe les ressources côté client en mode de développement et surveille les changements de fichier. L’observateur de fichiers force la regénération du regroupement chaque fois qu’un fichier projet change. L’optionmode
désactive les optimisations de production, comme la minimisation de l’arborescence (tree shaking). Utilisez uniquementbuild
dans le développement.release
: Regroupe les ressources côté client en mode de production.publish
: Exécute le scriptrelease
pour regrouper les ressources côté client en mode de production. La commande appelle la commande publish de CLI .NET pour publier l’application.
Créez un fichier nommé
*webpack.config.js
à la racine du projet avec le code suivant :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" }) ] };
Le fichier précédent configure la compilation Webpack. Détails de configuration à prendre en compte :
- La propriété
output
remplace la valeur par défaut dedist
. Le regroupement est émis dans le répertoirewwwroot
à la place. - Le tableau
resolve.extensions
inclut.js
pour importer le code JavaScript du client SignalR.
- La propriété
Créez un répertoire src à la racine du projet pour stocker les ressources côté client du projet.
Créez
src/index.html
avec le balisage suivant.<!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>
Le code HTML précédent définit le balisage réutilisable de la page d’accueil.
Créez un répertoire src/css. Son objectif est de stocker les fichiers
.css
du projet.Créez
src/css/main.css
avec le balisage suivant :*, *::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; }
Le fichier
main.css
précédent définit le style de l’application.Créez
src/tsconfig.json
avec le JSON suivant :{ "compilerOptions": { "target": "es5" } }
Le code précédent configure le compilateur TypeScript pour produire du code JavaScript compatible ECMAScript 5.
Créez
src/index.ts
avec le code suivant :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() { }
Le code TypeScript précédent récupère les références aux éléments DOM et joint deux gestionnaires d’événements :
keyup
: Cet événement se déclenche quand l’utilisateur tape des données dans la zone de textetbMessage
. La fonctionsend
est appelée quand l’utilisateur appuie sur la touche Entrée.click
: Cet événement se déclenche quand l’utilisateur clique sur le bouton Envoyer. La fonctionsend
est appelée.
Configurer l’application ASP.NET Core
Le code fourni dans la méthode
Startup.Configure
affiche Hello World!. Remplacez l’appel de méthodeapp.Run
par des appels à UseDefaultFiles(IApplicationBuilder) et UseStaticFiles(IApplicationBuilder).app.UseDefaultFiles(); app.UseStaticFiles();
Le code précédent permet au serveur de localiser et traiter le fichier
index.html
, que l’utilisateur entre son URL complète ou l’URL racine de l’application web.Appelez AddSignalR dans
Startup.ConfigureServices
. Il ajoute les services SignalR au projet.services.AddSignalR();
Mappez une route /hub au hub
ChatHub
. Ajoutez les lignes suivantes à la fin deStartup.Configure
:app.UseSignalR(options => { options.MapHub<ChatHub>("/hub"); });
Créez un répertoire Hubs à la racine du projet. Son objectif est de stocker le hub SignalR, qui est créé à l’étape suivante.
Créez un hub
Hubs/ChatHub.cs
avec le code suivant :using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace SignalRWebPack.Hubs { public class ChatHub : Hub { } }
Ajoutez le code suivant en haut du fichier
Startup.cs
pour résoudre la référence deChatHub
:using SignalRWebPack.Hubs;
Activer la communication entre le client et le serveur
Actuellement, l’application affiche un formulaire simple pour envoyer des messages. Rien ne se produit quand vous essayez de le faire. Le serveur écoute une route spécifique, mais ne fait rien avec les messages envoyés.
Exécutez la commande suivante à la racine du projet :
npm install @aspnet/signalr
La commande précédente installe le client TypeScriptSignalR, ce qui permet au client d’envoyer des messages au serveur.
Ajoutez le code mis en surbrillance au fichier
src/index.ts
: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() { }
Le code précédent prend en charge la réception de messages du serveur. La classe
HubConnectionBuilder
crée un générateur pour configurer la connexion de serveur. La fonctionwithUrl
configure l’URL du hub.SignalR permet l’échange de messages entre un client et un serveur. Chaque message a un nom spécifique. Par exemple, les messages portant le nom
messageReceived
peuvent exécuter la logique responsable de l’affichage du nouveau message dans la zone de messages. L’écoute d’un message spécifique peut être effectuée au moyen de la fonctionon
. Vous pouvez écouter n’importe quel nombre de noms de message. Vous pouvez aussi passer des paramètres au message, comme le nom de l’auteur et le contenu du message reçu. Dès que le client reçoit un message, un élémentdiv
est créé avec le nom de l’auteur et le contenu du message dans son attributinnerHTML
. Le nouveau message est ajouté à l’élément principaldiv
affichant les messages.Maintenant que le client peut recevoir un message, configurez-le pour en envoyer. Ajoutez le code mis en surbrillance au fichier
src/index.ts
: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 = ""); }
L’envoi d’un message au moyen de la connexion WebSocket nécessite l’appel de la méthode
send
. Le premier paramètre de la méthode est le nom du message. Les données du message se trouvent dans les autres paramètres. Dans cet exemple, un message identifié commenewMessage
est envoyé au serveur. Le message se compose du nom d’utilisateur et de l’entrée de l’utilisateur dans une zone de texte. Si l’envoi fonctionne, la valeur de la zone de texte est effacée.Ajoutez la méthode
NewMessage
à la classeChatHub
: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); } } }
Le code précédent diffuse les messages reçus à tous les utilisateurs connectés, une fois que le serveur les reçoit. Vous n’avez pas besoin d’appeler une méthode générique
on
pour recevoir tous les messages. Il vous suffit d’avoir une méthode du même nom que le message.Dans cet exemple, le client TypeScript envoie un message identifié comme
newMessage
. La méthode C#NewMessage
attend les données envoyées par le client. Un appel est effectué pour SendAsync sur Clients.All. Les messages reçus sont envoyés à tous les clients connectés au hub.
Test de l'application
Vérifiez que l’application fonctionne avec les étapes suivantes.
Exécuter Webpack en mode de mise en production. Dans la fenêtre Console du Gestionnaire de package, exécutez la commande suivante à la racine du projet. Si vous ne vous trouvez pas à la racine du projet, tapez
cd SignalRWebPack
avant d’entrer la commande.npm run release
Cette commande génère les ressources côté client à délivrer pendant l’exécution de l’application. Les ressources sont placées dans le dossier
wwwroot
.Webpack a effectué les tâches suivantes :
- Vide le contenu du répertoire
wwwroot
. - Converti le TypeScript en JavaScript dans un processus appelé transpilation.
- Troncation du code JavaScript généré pour réduire la taille de fichier dans un processus appelé minimisation.
- Copie des fichiers JavaScript, CSS et HTML traités à partir de
src
dans le répertoirewwwroot
. - Injection des éléments suivants dans le fichier
wwwroot/index.html
:- Balise
<link>
, référençant le fichierwwwroot/main.<hash>.css
. Cette balise est placée immédiatement avant la balise</head>
de fermeture. - Balise
<script>
, référençant le fichierwwwroot/main.<hash>.js
minifié. Cette balise est placée immédiatement après la balise de fermeture</title>
.
- Balise
- Vide le contenu du répertoire
Sélectionnez Déboguer>Démarrer sans débogage pour lancer l’application dans un navigateur sans attacher le débogueur. Le fichier
wwwroot/index.html
est servi àhttp://localhost:<port_number>
.Ouvrez une autre instance de navigateur (n’importe quel navigateur). Copiez l’URL de la barre d’adresse.
Choisissez un navigateur, tapez quelque chose dans la zone de texte Message, puis cliquez sur le bouton Envoyer. Le nom unique de l’utilisateur et le message sont affichés instantanément dans les deux pages.
Ressources supplémentaires
Commentaires
https://aka.ms/ContentUserFeedback.
Prochainement : Tout au long de l'année 2024, nous supprimerons progressivement les GitHub Issues en tant que mécanisme de retour d'information pour le contenu et nous les remplacerons par un nouveau système de retour d'information. Pour plus d’informations, voir:Soumettre et afficher des commentaires pour