快速入门:使用 SignalR 服务创建聊天室Quickstart: Create a chat room by using SignalR Service

Azure SignalR 服务是一项 Azure 服务,可帮助开发者轻松生成具有实时功能的 Web 应用程序。Azure SignalR Service is an Azure service that helps developers easily build web applications with real-time features. 此服务最初基于 SignalR for ASP.NET Core 2.1,但现在支持更高版本。This service was originally based on SignalR for ASP.NET Core 2.1, but now supports later versions.

本文介绍如何开始使用 Azure SignalR 服务。This article shows you how to get started with the Azure SignalR Service. 在本快速入门中,你将使用 ASP.NET Core MVC Web 应用创建一个聊天应用程序。In this quickstart, you'll create a chat application by using an ASP.NET Core MVC web app. 此应用将与 Azure SignalR 服务资源建立连接,以启用实时内容更新。This app will make a connection with your Azure SignalR Service resource to enable real-time content updates. 将在本地托管该 Web 应用程序并与多个浏览器客户端连接。You'll host the web application locally and connect with multiple browser clients. 每个客户端都可以将内容更新推送到所有其他客户端。Each client will be able to push content updates to all other clients.

可使用任何代码编辑器来完成本快速入门中的步骤。You can use any code editor to complete the steps in this quickstart. 一个选项是适用于 Windows、macOS 和 Linux 平台的 Visual Studio CodeOne option is Visual Studio Code, which is available on the Windows, macOS, and Linux platforms.

本教程所用代码可在 AzureSignalR-samples GitHub 存储库下载。The code for this tutorial is available for download in the AzureSignalR-samples GitHub repository. 此外,可以遵循创建 SignalR 服务脚本来创建本快速入门中所用的 Azure 资源。Also, you can create the Azure resources used in this quickstart by following Create a SignalR Service script.

If you don't have an Azure subscription, create a free account before you begin.


存在问题?请告诉我们。Having issues? Let us know.

创建 Azure SignalR 资源Create an Azure SignalR resource

  1. 若要创建 Azure SignalR 服务资源,请先登录到 Azure 门户To create an Azure SignalR Service resource, first sign in to the Azure portal. 在页面的左上角,选择“+ 创建资源” 。In the upper-left side of the page, select + Create a resource. 在“搜索市场”文本框中,输入“SignalR 服务”。 In the Search the Marketplace text box, enter SignalR Service.

  2. 在结果中选择“SignalR 服务”,然后选择“创建”。 Select SignalR Service in the results, and select Create.

  3. 在新的“SignalR” 设置页上,为新的 SignalR 资源添加以下设置:On the new SignalR settings page, add the following settings for your new SignalR resource:

    NameName 建议的值Recommended value 说明Description
    资源名称Resource name testsignalrtestsignalr 输入用于 SignalR 资源的唯一资源名称。Enter a unique resource name to use for the SignalR resource. 该名称必须是包含 1 到 63 个字符的字符串,只能包含数字、字母和连字符 (-) 字符。The name must be a string of 1 to 63 characters and contain only numbers, letters, and the hyphen (-) character. 该名称的开头或末尾不能是连字符字符,并且连续的连字符字符无效。The name cannot start or end with the hyphen character, and consecutive hyphen characters are not valid.
    SubscriptionSubscription 选择自己的订阅Choose your subscription 选择要用来测试 SignalR 的 Azure 订阅。Select the Azure subscription that you want to use to test SignalR. 如果帐户只有一个订阅,则会自动选择该订阅并且不显示“订阅”下拉菜单 。If your account has only one subscription, it's automatically selected and the Subscription drop-down isn't displayed.
    Resource groupResource group 创建一个名为 SignalRTestResources 的资源组Create a resource group named SignalRTestResources 为 SignalR 资源选择或创建资源组。Select or create a resource group for your SignalR resource. 此组可用于组织多个资源,删除该资源组可以同时删除这些资源。This group is useful for organizing multiple resources that you might want to delete at the same time by deleting the resource group. 有关详细信息,请参阅 Using resource groups to manage your Azure resources(使用资源组管理 Azure 资源)。For more information, see Using resource groups to manage your Azure resources.
    位置Location 中国东部China East 使用“位置”指定在其中托管 SignalR 资源的地理位置 。Use Location to specify the geographic location in which your SignalR resource is hosted. 为获得最佳性能,我们建议在应用程序的其他组件所在的同一区域创建资源。For the best performance, we recommend that you create the resource in the same region as other components of your application.
    定价层Pricing tier 免费Free 目前可以使用“免费”和“标准”选项。 Currently, Free and Standard options are available.
    固定到仪表板Pin to dashboard 选中此框可将资源固定到仪表板,以方便查找。Select this box to have the resource pinned to your dashboard so it's easier to find.
  4. 选择“创建” 。Select Create. 部署可能需要几分钟时间才能完成。The deployment might take a few minutes to complete.

  5. 部署完成后,在“设置”下选择“密钥”。 After the deployment is complete, select Keys under SETTINGS. 复制主密钥的连接字符串。Copy your connection string for the primary key. 稍后要使用此字符串将应用配置为使用 Azure SignalR 服务资源。You'll use this string later to configure your app to use the Azure SignalR Service resource.

    该连接字符串采用以下格式:The connection string will have the following form:


存在问题?请告诉我们。Having issues? Let us know.

创建一个 ASP.NET Core Web 应用Create an ASP.NET Core web app

在本部分,你将使用 .NET Core命令行接口 (CLI) 创建一个 ASP.NET Core MVC Web 应用项目。In this section, you use the .NET Core command-line interface (CLI) to create an ASP.NET Core MVC web app project. 通过 Visual Studio 使用 .NET Core CLI 的优点是,它可用于 Windows、macOS 和 Linux 平台。The advantage of using the .NET Core CLI over Visual Studio is that it's available across the Windows, macOS, and Linux platforms.

  1. 为项目创建一个文件夹。Create a folder for your project. 本快速入门使用 E:\Testing\chattest 文件夹。This quickstart uses the E:\Testing\chattest folder.

  2. 在新文件夹中,运行以下命令以创建项目:In the new folder, run the following command to create the project:

    dotnet new mvc

存在问题?请告诉我们。Having issues? Let us know.

向项目添加机密管理器Add Secret Manager to the project

在本部分,你要将机密管理器工具添加到项目。In this section, you'll add the Secret Manager tool to your project. 机密管理器工具存储敏感数据,以用于项目树外部的开发工作。The Secret Manager tool stores sensitive data for development work outside your project tree. 此方法有助于防止意外共享源代码中的应用机密。This approach helps prevent the accidental sharing of app secrets in source code.

  1. 打开 .csproj 文件 。Open your .csproj file. 添加 DotNetCliToolReference 元素以包含 Microsoft.Extensions.SecretManager.Tools 。Add a DotNetCliToolReference element to include Microsoft.Extensions.SecretManager.Tools . 另外,为 chattest.csproj 添加以下代码中所示的 UserSecretsId 元素,并保存文件。Also add a UserSecretsId element as shown in the following code for chattest.csproj , and save the file.

    <Project Sdk="Microsoft.NET.Sdk.Web">
        <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
        <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.2" />

将 Azure SignalR 添加到 Web 应用Add Azure SignalR to the web app

  1. 通过运行以下命令,添加对 Microsoft.Azure.SignalR NuGet 包的引用:Add a reference to the Microsoft.Azure.SignalR NuGet package by running the following command:

    dotnet add package Microsoft.Azure.SignalR
  2. 运行以下命令,还原项目包:Run the following command to restore packages for your project:

    dotnet restore
  3. 向机密管理器添加名为“Azure: SignalR:ConnectionString”的机密 。Add a secret named Azure:SignalR:ConnectionString to Secret Manager.

    此机密将包含用于访问 SignalR 服务资源的连接字符串。This secret will contain the connection string to access your SignalR Service resource. Azure:SignalR:ConnectionString 是 SignalR 查找的用于建立连接的默认配置密钥。Azure:SignalR:ConnectionString is the default configuration key that SignalR looks for to establish a connection. 将以下命令中的值替换为 SignalR 服务资源的连接字符串。Replace the value in the following command with the connection string for your SignalR Service resource.

    必须在 .csproj 文件所在的同一目录中运行此命令。You must run this command in the same directory as the .csproj file.

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

    机密管理器仅用于在本地托管 Web 应用时对其进行测试。Secret Manager will be used only for testing the web app while it's hosted locally. 后一篇教程会介绍如何将聊天 Web 应用部署到 Azure。In a later tutorial, you'll deploy the chat web app to Azure. 将 Web 应用部署到 Azure 后,你将使用应用程序设置,而不是使用机密管理器存储连接字符串。After the web app is deployed to Azure, you'll use an application setting instead of storing the connection string with Secret Manager.

    此机密使用配置 API 进行访问。This secret is accessed with the Configuration API. 在所有支持的平台上,冒号 (:) 可以在配置 API 的配置名称中使用。A colon (:) works in the configuration name with the Configuration API on all supported platforms. 请参阅按环境进行的配置See Configuration by environment.

  4. 打开 Startup.cs,并通过调用 AddSignalR()AddAzureSignalR() 方法更新 ConfigureServices 方法,从而使用 Azure SignalR 服务:Open Startup.cs and update the ConfigureServices method to use Azure SignalR Service by calling the AddSignalR() and AddAzureSignalR() methods:

    public void ConfigureServices(IServiceCollection services)

    此代码不会向 AddAzureSignalR() 传递参数,而是使用默认配置密钥作为 SignalR 服务资源连接字符串。By not passing a parameter to AddAzureSignalR(), this code uses the default configuration key for the SignalR Service resource connection string. 默认配置密钥为 Azure:SignalR:ConnectionStringThe default configuration key is Azure:SignalR:ConnectionString .

  5. 在 Startup.cs 中,更新 Configure 方法并将其替换为以下代码。In Startup.cs , update the Configure method by replacing it with the following code.

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        app.UseEndpoints(endpoints =>

添加集线器类Add a hub class

在 SignalR 中,集线器是核心组件,用于公开一组可从客户端调用的方法。In SignalR, a hub is a core component that exposes a set of methods that can be called from the client. 本部分通过两种方法定义集线器类:In this section, you define a hub class with two methods:

  • Broadcast设置用户帐户 :此方法向所有客户端广播消息。Broadcast: This method broadcasts a message to all clients.
  • Echo设置用户帐户 :此方法将消息发送回调用方。Echo: This method sends a message back to the caller.

这两个方法都使用 ASP.NET Core SignalR SDK 提供的 Clients 接口。Both methods use the Clients interface that the ASP.NET Core SignalR SDK provides. 使用此接口可以访问所有已连接的客户端,因此你可将内容推送到客户端。This interface gives you access to all connected clients, so you can push content to your clients.

  1. 在项目目录中,添加名为“Hub”的新文件夹 。In your project directory, add a new folder named Hub . 将名为 ChatHub.cs 的新中心代码文件添加到新文件夹。Add a new hub code file named ChatHub.cs to the new folder.

  2. 将以下代码添加到 ChatHub.cs 以定义中心类,然后保存该文件。Add the following code to ChatHub.cs to define your hub class and save the file.

    如果使用的项目名称与 SignalR.Mvc 不同,请更新此类的命名空间。Update the namespace for this class if you used a project name that differs from SignalR.Mvc .

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    namespace SignalR.Mvc
        public class ChatHub : Hub
            public Task BroadcastMessage(string name, string message) =>
                Clients.All.SendAsync("broadcastMessage", name, message);
            public Task Echo(string name, string message) =>
                       .SendAsync("echo", name, $"{message} (echo from server)");

添加 Web 应用的客户端接口Add the client interface for the web app

此聊天室应用的客户端用户界面由 wwwroot 目录中名为 index.html 的文件中的 HTML 和 JavaScript 组成。The client user interface for this chat room app will consist of HTML and JavaScript in a file named index.html in the wwwroot directory.

示例存储库的 wwwroot 文件夹复制 css/site.css 文件 。Copy the css/site.css file from the wwwroot folder of the samples repository. 将项目的 css/site.css 替换为复制的内容。Replace your project's css/site.css with the one you copied.

下面是 index.html 的主代码:Here's the main code of index.html :

在名为 index.html 的 wwwroot 目录中创建新文件,将以下 HTML 复制并粘贴到新创建的文件中 :Create a new file in the wwwroot directory named index.html , copy, and paste the following HTML into the newly created file:

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

    <!--Reference the SignalR library. -->
    <script src="https://cdn.jsdelivr.net/npm/@microsoft/signalr@3.1.8/dist/browser/signalr.min.js"></script>

    <!--Add script to update the page and send messages.-->
    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function () {

            const generateRandomName = () =>
                Math.random().toString(36).substring(2, 10);

            let username = generateRandomName();
            const promptMessage = 'Enter your name:';
            do {
                username = prompt(promptMessage, username);
                if (!username || username.startsWith('_') || username.indexOf('<') > -1 || username.indexOf('>') > -1) {
                    username = '';
                    promptMessage = 'Invalid input. Enter your name:';
            } while (!username)

            const messageInput = document.getElementById('message');

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

            function bindConnectionMessage(connection) {
                var messageCallback = function (name, message) {
                    if (!message) return;
                    var encodedName = name;
                    var encodedMsg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
                    var messageEntry = createMessageEntry(encodedName, encodedMsg);

                    var messageBox = document.getElementById('messages');
                    messageBox.scrollTop = messageBox.scrollHeight;
                connection.on('broadcastMessage', messageCallback);
                connection.on('echo', messageCallback);

            function onConnected(connection) {
                console.log('connection started');
                connection.send('broadcastMessage', '_SYSTEM_', username + ' JOINED');
                document.getElementById('sendmessage').addEventListener('click', function (event) {
                    if (messageInput.value) {
                        connection.send('broadcastMessage', username, messageInput.value);

                    messageInput.value = '';
                document.getElementById('message').addEventListener('keypress', function (event) {
                    if (event.keyCode === 13) {
                        return false;
                document.getElementById('echo').addEventListener('click', function (event) {
                    connection.send('echo', username, messageInput.value);

                    messageInput.value = '';

            function onConnectionError(error) {
                if (error && error.message) {
                var modal = document.getElementById('myModal');
                modal.style = 'display: block;';

            const connection = new signalR.HubConnectionBuilder()
                .then(() => onConnected(connection))
                .catch(error => console.error(error.message));

index.html 中的代码调用 HubConnectionBuilder.build(),以便与 Azure SignalR 资源建立 HTTP 连接。The code in index.html calls HubConnectionBuilder.build() to make an HTTP connection to the Azure SignalR resource.

如果连接成功,则会将该连接传递到 bindConnectionMessage,这会向客户端添加传入内容推送的事件处理程序。If the connection is successful, that connection is passed to bindConnectionMessage, which adds event handlers for incoming content pushes to the client.

HubConnection.start() 启动与中心之间的通信。HubConnection.start() starts communication with the hub. 然后,onConnected() 添加按钮事件处理程序。Then, onConnected() adds the button event handlers. 这些处理程序使用连接,让此客户端将内容更新推送到所有连接的客户端。These handlers use the connection to allow this client to push content updates to all connected clients.

添加开发运行时配置文件Add a development runtime profile

在本部分,你将为 ASP.NET Core 添加开发运行时环境。In this section, you'll add a development runtime environment for ASP.NET Core. 有关详细信息,请参阅在 ASP.NET Core 中使用多个环境For more information, see Work with multiple environments in ASP.NET Core.

  1. 在项目中创建名为 Properties 的文件夹。Create a folder named Properties in your project.

  2. 将包含以下内容的名为 launchSettings.json 的新文件添加到该文件夹,然后保存文件。Add a new file named launchSettings.json to the folder, with the following content, and save the file.

        "profiles" : {
            "ChatRoom": {
                "commandName": "Project",
                "launchBrowser": true,
                "environmentVariables": {
                    "ASPNETCORE_ENVIRONMENT": "Development"
                "applicationUrl": "http://localhost:5000/"

存在问题?请告诉我们。Having issues? Let us know.

在本地生成并运行应用Build and run the app locally

  1. 要通过使用 .NET Core CLI 生成应用,请在命令行界面中执行以下命令:To build the app by using the .NET Core CLI, run the following command in the command shell:

    dotnet build
  2. 生成成功完成后,运行以下命令以在本地运行 Web 应用:After the build successfully finishes, run the following command to run the web app locally:

    dotnet run

    根据开发运行时配置文件中的配置,该应用将在端口 5000 上本地托管:The app will be hosted locally on port 5000, as configured in our development runtime profile:

    info: Microsoft.Hosting.Lifetime[0]
          Now listening on: https://localhost:5001
    info: Microsoft.Hosting.Lifetime[0]
          Now listening on: http://localhost:5000
    info: Microsoft.Hosting.Lifetime[0]
          Application started. Press Ctrl+C to shut down.
    info: Microsoft.Hosting.Lifetime[0]
          Hosting environment: Development
    info: Microsoft.Hosting.Lifetime[0]
          Content root path: E:\Testing\chattest
  3. 打开两个浏览器窗口。Open two browser windows. 在每个浏览器中,转到 http://localhost:5000In each browser, go to http://localhost:5000. 系统会提示你输入名称。You're prompted to enter your name. 输入两个客户端的客户端名称,然后使用“发送”按钮测试能否在两个客户端之间推送消息内容 。Enter a client name for both clients and test pushing message content between both clients by using the Send button.

    Azure SignalR 群组聊天示例

存在问题?请告诉我们。Having issues? Let us know.

清理资源Clean up resources

如果你想要继续学习下一篇教程,可以保留本快速入门中创建的资源,以便重复使用。If you'll continue to the next tutorial, you can keep the resources created in this quickstart and reuse them.

如果已完成快速入门示例应用程序,请删除本快速入门中创建的 Azure 资源,以免产生费用。If you're finished with the quickstart sample application, you can delete the Azure resources created in this quickstart to avoid charges.


删除资源组是不可逆的操作,会同时删除该组中包含的所有资源。Deleting a resource group is irreversible and includes all the resources in that group. 请确保不要意外删除错误的资源组或资源。Make sure that you don't accidentally delete the wrong resource group or resources. 如果在现有资源组(其中包含要保留的资源)中为托管此示例而创建了相关资源,可从其边栏选项卡中逐个删除这些资源,而不要删除资源组。If you created the resources for hosting this sample in an existing resource group that contains resources you want to keep, you can delete each resource individually from its blade instead of deleting the resource group.

登录到 Azure 门户,然后选择“资源组”。 Sign in to the Azure portal and select Resource groups .

在“按名称筛选”文本框中键入资源组的名称 。In the Filter by name text box, type the name of your resource group. 本快速入门的说明使用了名为“SignalRTestResources”的资源组 。The instructions for this quickstart used a resource group named SignalRTestResources . 在结果列表中的资源组上选择省略号 ( ... ),然后选择“删除资源组” 。On your resource group in the result list, select the ellipsis ( ... ) > Delete resource group .


系统会要求确认是否删除资源组。You're asked to confirm the deletion of the resource group. 重新键入资源组的名称进行确认,然后选择“删除” 。Enter the name of your resource group to confirm, and select Delete .

片刻之后,将会删除该资源组及其所有资源。After a few moments, the resource group and all of its resources are deleted.

存在问题?请告诉我们。Having issues? Let us know.

后续步骤Next steps

在本快速入门中,你已创建一个新的 Azure SignalR 服务资源。In this quickstart, you created a new Azure SignalR Service resource. 然后,已将此资源与 ASP.NET Core Web 应用配合使用,以将内容更新实时推送到多个连接的客户端。You then used it with an ASP.NET Core web app to push content updates in real time to multiple connected clients. 若要详细了解如何使用 Azure SignalR 服务,请继续学习有关身份验证的演示教程。To learn more about using Azure SignalR Service, continue to the tutorial that demonstrates authentication.

存在问题?请告诉我们。Having issues? Let us know.