本教程介绍使用 SignalR 生成实时应用的基础知识。 您将学习如何:
最终将创建一个正常运行的聊天应用:
Visual Studio Code 说明使用用于 ASP.NET Core 的 .NET Core CLI 开发功能,如项目创建。 可在任何平台(macOS、Linux 或 Windows)上或在任何代码编辑器中遵循这些说明。 如果使用 Visual Studio Code 以外的其他内容,则可能需要进行少量更改。
从菜单中选择“文件”>“新建项目” 。
在“创建新项目”对话框中,选择“ASP.NET Core Web 应用程序”,然后选择“下一步” 。
在“配置新项目”对话框中,为项目 SignalRChat 命名,然后选择“创建” 。
在“创建新的 ASP.NET Core Web 应用程序”对话框中,选择“.NET Core”和“ASP.NET Core 3.0” 。
选择“Web 应用程序”以创建使用 Razor Pages 的项目,然后选择“创建” 。
在将要在其中创建新项目文件夹的文件夹中打开集成终端。
运行以下命令:
dotnet new webapp -o SignalRChat code -r SignalRChat
从菜单中选择“文件”>“新建解决方案” 。
选择“.NET Core”>“应用”>“Web 应用程序”(不要选择“Web 应用程序(Model-View-Controller)”),然后选择“下一步” 。
确保“目标框架”设置为“.NET Core 3.0”,然后选择“下一步” 。
将项目命名为“SignalRChat”,然后选择“创建” 。
SignalR 服务器库包含在 ASP.NET Core 3.0 共享框架中。 JavaScript 客户端库不会自动包含在项目中。 对于此教程,使用库管理器 (LibMan) 从 unpkg 获取客户端库。 unpkg 是一个内容分发网络 (CDN),可以分发在 npm(即 Node.js 包管理器)中找到的任何内容。
在“解决方案资源管理器” 中,右键单击项目,然后选择“添加” >“客户端库” 。
在“添加客户端库” 对话框中,对于“提供程序” ,选择“unpkg” 。
对于“库” ,输入 @microsoft/signalr@latest
。
选择“选择特定文件” ,展开“dist/browser” 文件夹,然后选择“signalr.js” 和“signalr.min.js” 。
将“目标位置” 设置为 wwwroot/js/signalr/ ,然后选择“安装” 。
LibMan 创建 wwwroot/js/signalr 文件夹并将所选文件复制到该文件夹。
在集成终端中,运行以下命令以安装 LibMan。
dotnet tool install -g Microsoft.Web.LibraryManager.Cli
使用 LibMan 运行以下命令,以获取 SignalR 客户端库。 可能需要等待几秒钟的时间才能看到输出。
libman install @microsoft/signalr@latest -p unpkg -d wwwroot/js/signalr --files dist/browser/signalr.js --files dist/browser/signalr.min.js
参数指定以下选项:
输出如下所示:
wwwroot/js/signalr/dist/browser/signalr.js written to disk wwwroot/js/signalr/dist/browser/signalr.min.js written to disk Installed library "@microsoft/signalr@latest" to "wwwroot/js/signalr"
在“终端” 中,运行以下命令以安装 LibMan。
dotnet tool install -g Microsoft.Web.LibraryManager.Cli
导航到项目文件夹(包含 SignalRChat.csproj 文件的文件夹)。
使用 LibMan 运行以下命令,以获取 SignalR 客户端库。
libman install @microsoft/signalr@latest -p unpkg -d wwwroot/js/signalr --files dist/browser/signalr.js --files dist/browser/signalr.min.js
参数指定以下选项:
输出如下所示:
wwwroot/js/signalr/dist/browser/signalr.js written to disk wwwroot/js/signalr/dist/browser/signalr.min.js written to disk Installed library "@microsoft/signalr@latest" to "wwwroot/js/signalr"
中心是一个类,用作处理客户端 - 服务器通信的高级管道。
在 SignalRChat 项目文件夹中,创建 Hubs 文件夹 。
在 Hubs 文件夹中,使用以下代码创建 ChatHub.cs 文件 :
using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace SignalRChat.Hubs { public class ChatHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } } }
ChatHub
类继承自 SignalR Hub
。 Hub
类管理连接、组和消息。
可通过已连接客户端调用 SendMessage
,以向所有客户端发送消息。 本教程后面部分将显示调用该方法的 JavaScript 客户端代码。 SignalR 代码是异步模式,可提供最大的可伸缩性。
必须将 SignalR 服务器配置为将 SignalR 请求传递给 SignalR。
将以下突出显示的代码添加到 Startup.cs 文件 。
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using SignalRChat.Hubs; namespace SignalRChat { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddSignalR(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapHub<ChatHub>("/chatHub"); }); } } }
这些更改将 SignalR 添加到 ASP.NET Core 依赖关系注入和路由系统。
使用以下代码替换 Pages\Index.cshtml 中的内容 :
@page <div class="container"> <div class="row"> </div> <div class="row"> <div class="col-2">User</div> <div class="col-4"><input type="text" id="userInput" /></div> </div> <div class="row"> <div class="col-2">Message</div> <div class="col-4"><input type="text" id="messageInput" /></div> </div> <div class="row"> </div> <div class="row"> <div class="col-6"> <input type="button" id="sendButton" value="Send Message" /> </div> </div> </div> <div class="row"> <div class="col-12"> <hr /> </div> </div> <div class="row"> <div class="col-6"> <ul id="messagesList"></ul> </div> </div> <script src="~/js/signalr/dist/browser/signalr.js"></script> <script src="~/js/chat.js"></script>
前面的代码:
id="messagesList"
创建一个列表,用于显示从 SignalR 中心接收的消息。在 wwwroot/js 文件夹中,使用以下代码创建 chat.js 文件 :
"use strict"; var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build(); //Disable send button until connection is established document.getElementById("sendButton").disabled = true; connection.on("ReceiveMessage", function (user, message) { var msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); var encodedMsg = user + " says " + msg; var li = document.createElement("li"); li.textContent = encodedMsg; document.getElementById("messagesList").appendChild(li); }); connection.start().then(function () { document.getElementById("sendButton").disabled = false; }).catch(function (err) { return console.error(err.toString()); }); document.getElementById("sendButton").addEventListener("click", function (event) { var user = document.getElementById("userInput").value; var message = document.getElementById("messageInput").value; connection.invoke("SendMessage", user, message).catch(function (err) { return console.error(err.toString()); }); event.preventDefault(); });
前面的代码:
在集成终端中,运行以下命令:
dotnet watch run -p SignalRChat.csproj
从地址栏复制 URL,打开另一个浏览器实例或选项卡,并在地址栏中粘贴该 URL。
选择任一浏览器,输入名称和消息,然后选择“发送消息”按钮 。
两个页面上立即显示名称和消息。
提示
如果应用不起作用,请打开浏览器开发人员工具 (F12) 并转到控制台。 可能会看到与 HTML 和 JavaScript 代码相关的错误。 例如,假设将 signalr.js 放在不同于系统指示的文件夹中 。 在这种情况下,对该文件的引用将不起作用,并且你将在控制台中看到 404 错误。
如果 Chrome 中出现 ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY 错误,请运行这些命令以更新开发证书:
dotnet dev-certs https --clean dotnet dev-certs https --trust
本教程介绍使用 SignalR 生成实时应用的基础知识。 您将学习如何:
警告
如果使用 Visual Studio 2017,请参阅 dotnet/sdk 问题 #3124,以了解无法与 Visual Studio 一起使用的 .NET Core SDK 版本的信息。
Visual Studio Code 说明使用用于 ASP.NET Core 的 .NET Core CLI 开发功能,如项目创建。 可在任何平台(macOS、Linux 或 Windows)上或在任何代码编辑器中遵循这些说明。 如果使用 Visual Studio Code 以外的其他内容,则可能需要进行少量更改。
从菜单中选择“文件”>“新建项目” 。
在“新建项目”对话框中,选择“已安装”>“Visual C#”>“Web”>“ASP.NET Core Web 应用” 。 将项目命名为“SignalRChat” 。
选择“Web 应用”,以创建使用 Razor Pages 的项目 。
选择“.NET Core”目标框架,选择“ASP.NET Core 2.2”,然后单击“确定” 。
在将要在其中创建新项目文件夹的文件夹中打开集成终端。
运行以下命令:
dotnet new webapp -o SignalRChat code -r SignalRChat
从菜单中选择“文件”>“新建解决方案” 。
选择“.NET Core”>“应用”>“ASP.NET Core Web 应用”(请勿选择 ASP.NET Core Web 应用 (MVC)) 。
选择“下一步” 。
将项目命名为“SignalRChat”,然后选择“创建” 。
Microsoft.AspNetCore.App
元包中包括 SignalR 服务器库。 JavaScript 客户端库不会自动包含在项目中。 对于此教程,使用库管理器 (LibMan) 从 unpkg 获取客户端库。 unpkg 是一个内容分发网络 (CDN),可以分发在 npm(即 Node.js 包管理器)中找到的任何内容。
在“解决方案资源管理器” 中,右键单击项目,然后选择“添加” >“客户端库” 。
在“添加客户端库” 对话框中,对于“提供程序” ,选择“unpkg” 。
对于“库” ,输入 @microsoft/signalr@3
,然后选择不是预览版的最新版本。
选择“选择特定文件” ,展开“dist/browser” 文件夹,然后选择“signalr.js” 和“signalr.min.js” 。
将“目标位置” 设置为 wwwroot/lib/signalr/ ,然后选择“安装” 。
LibMan 创建 wwwroot/lib/signalr 文件夹并将所选文件复制到该文件夹。
在集成终端中,运行以下命令以安装 LibMan。
dotnet tool install -g Microsoft.Web.LibraryManager.Cli
使用 LibMan 运行以下命令,以获取 SignalR 客户端库。 可能需要等待几秒钟的时间才能看到输出。
libman install @microsoft/signalr -p unpkg -d wwwroot/lib/signalr --files dist/browser/signalr.js --files dist/browser/signalr.min.js
参数指定以下选项:
输出如下所示:
wwwroot/lib/signalr/dist/browser/signalr.js written to disk wwwroot/lib/signalr/dist/browser/signalr.min.js written to disk Installed library "@microsoft/signalr@3.0.1" to "wwwroot/lib/signalr"
在“终端” 中,运行以下命令以安装 LibMan。
dotnet tool install -g Microsoft.Web.LibraryManager.Cli
导航到项目文件夹(包含 SignalRChat.csproj 文件的文件夹)。
使用 LibMan 运行以下命令,以获取 SignalR 客户端库。
libman install @microsoft/signalr -p unpkg -d wwwroot/lib/signalr --files dist/browser/signalr.js --files dist/browser/signalr.min.js
参数指定以下选项:
输出如下所示:
wwwroot/lib/signalr/dist/browser/signalr.js written to disk wwwroot/lib/signalr/dist/browser/signalr.min.js written to disk Installed library "@microsoft/signalr@3.x.x" to "wwwroot/lib/signalr"
中心是一个类,用作处理客户端 - 服务器通信的高级管道。
在 SignalRChat 项目文件夹中,创建 Hubs 文件夹 。
在 Hubs 文件夹中,使用以下代码创建 ChatHub.cs 文件 :
using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace SignalRChat.Hubs { public class ChatHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } } }
ChatHub
类继承自 SignalR Hub
。 Hub
类管理连接、组和消息。
可通过已连接客户端调用 SendMessage
,以向所有客户端发送消息。 本教程后面部分将显示调用该方法的 JavaScript 客户端代码。 SignalR 代码是异步模式,可提供最大的可伸缩性。
必须将 SignalR 服务器配置为将 SignalR 请求传递给 SignalR。
将以下突出显示的代码添加到 Startup.cs 文件 。
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using SignalRChat.Hubs; namespace SignalRChat { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddSignalR(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseSignalR(routes => { routes.MapHub<ChatHub>("/chatHub"); }); app.UseMvc(); } } }
这些更改将 SignalR 添加到 ASP.NET Core 依赖关系注入系统和中间件管道。
使用以下代码替换 Pages\Index.cshtml 中的内容 :
@page <div class="container"> <div class="row"> </div> <div class="row"> <div class="col-6"> </div> <div class="col-6"> User..........<input type="text" id="userInput" /> <br /> Message...<input type="text" id="messageInput" /> <input type="button" id="sendButton" value="Send Message" /> </div> </div> <div class="row"> <div class="col-12"> <hr /> </div> </div> <div class="row"> <div class="col-6"> </div> <div class="col-6"> <ul id="messagesList"></ul> </div> </div> </div> <script src="~/lib/signalr/dist/browser/signalr.js"></script> <script src="~/js/chat.js"></script>
前面的代码:
id="messagesList"
创建一个列表,用于显示从 SignalR 中心接收的消息。在 wwwroot/js 文件夹中,使用以下代码创建 chat.js 文件 :
"use strict"; var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build(); //Disable send button until connection is established document.getElementById("sendButton").disabled = true; connection.on("ReceiveMessage", function (user, message) { var msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); var encodedMsg = user + " says " + msg; var li = document.createElement("li"); li.textContent = encodedMsg; document.getElementById("messagesList").appendChild(li); }); connection.start().then(function(){ document.getElementById("sendButton").disabled = false; }).catch(function (err) { return console.error(err.toString()); }); document.getElementById("sendButton").addEventListener("click", function (event) { var user = document.getElementById("userInput").value; var message = document.getElementById("messageInput").value; connection.invoke("SendMessage", user, message).catch(function (err) { return console.error(err.toString()); }); event.preventDefault(); });
前面的代码:
在集成终端中,运行以下命令:
dotnet run -p SignalRChat.csproj
从地址栏复制 URL,打开另一个浏览器实例或选项卡,并在地址栏中粘贴该 URL。
选择任一浏览器,输入名称和消息,然后选择“发送消息”按钮 。
两个页面上立即显示名称和消息。
提示
如果应用不起作用,请打开浏览器开发人员工具 (F12) 并转到控制台。 可能会看到与 HTML 和 JavaScript 代码相关的错误。 例如,假设将 signalr.js 放在不同于系统指示的文件夹中 。 在这种情况下,对该文件的引用将不起作用,并且你将在控制台中看到 404 错误。