ASP.NET Core SignalR (三):教程
此为系列文章,对MSDN ASP.NET Core SignalR 的官方文档进行系统学习与翻译。其中或许会添加本人对 ASP.NET Core 的浅显理解。
本教程会教你使用SignalR建立实时app的一些基础知识。你将会学到如何:
- 创建一个Web项目
- 添加SignalR 客户端库
- 创建一个SignalR 中心
- 配置项目以使用SignalR
- 添加从任何客户端向所有已连接的客户端发送消息的代码
最终,你将得到一个工作聊天app:
准备条件
- Visual Studio 2019, 其具有ASP.NET 以及 Web 开发工作负载。
- .NET Core 3.0 SDK 或者后续版本
创建一个Web app 工程
- 在菜单栏,选择 文件 > 新建工程
- 在 创建新工程 对话框 中,选择 ASP.NET Core Web app,然后选择 下一步
- 在 配置你的新工称 对话框 中,将工程命名为SignalRChat,然后选择 新建
- 在 创建新的 ASP.NET Core Web程序对话框中,选择 .NET Core 以及 ASP.NET Core 3.0
- 选择 Web 应用程序 以创建使用Razor 页的项目,然后 选择 创建
添加SignalR 客户端库
SignalR 服务端库已经包含在 ASP.NET Core 3.0 共享框架中。而Javascript 客户端库不会自动包含在客户端库中。对于本教程来说,你将使用 库管理器(LibMan)来从unpkg 获取客户端库。unpkg 是一个CDN,其可以传送在 npm(Node Pakage Manager)中找到的任何东西。
- 在解决方案资源管理器中,右键项目,选择 添加 > 客户端库
- 在添加客户端库 对话框 中,对于 提供者 选择 unpkg
- 对于类库,输入
@microsoft/signalr@latest
- 选择 选择特定的文件,展开 dist/browser 文件夹,选择signalr.js and signalr.min.js
- 将目标路径设置为 wwwroot/js/signalr/ ,选择 安装
LibMan 会创建一个wwwroot/js/signalr 文件夹,并将复制的文件拷贝给它。
创建一个 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 服务必须要进行配置来给Signal 传递 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 DI 以及 路由系统中。
添加SignalR客户端代码
使用如下的代码来替换 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>
上述代码:
- 创建了 name文本框,message 文本框,以及一个提交按钮。
- 创建了一个 id 为 messagesList 的列表,用来显示从SignalR 中心接受到的消息。
- 包含引用了 SignalR 的脚本,并包含了 你将在下一节创建的 chat.js 应用程序代码。
在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(); });
上述代码:
- 创建并开启了一个连接。
- 向提交按钮添加了一个处理器,其可以向 SignalR中心发送消息。
- 向连接对象添加了一个处理器,其可以从 中心接收 消息 并将它们追加到列表中。
运行app
- 运行App
- 从地址栏中复制URL,打开另一个浏览器实例或者标签页,将URL粘贴到地址栏。
- 选择任意一个浏览器,输入 name 和 message,点击 发送。
- name 和 message 会立即显示在两个 浏览器上。
提示:
如果app 没有正常工作,打开你的浏览器开发工具(F12),找到控制台。你或许会看到与你的HTML 和 Javascript代码相关的异常。举个例子,假设你将signalr.js 文件放到与指导文档不同的文件夹,这种情况下,该文件的引用便不会工作,而你将看到一个 404。
如果你在Chrome中得到了一个错误:ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY,运行如下命令来更新你的开发凭证:
dotnet dev-certs https --clean
dotnet dev-certs https --trust