本章将和大家分享使用 SignalR 生成实时应用的基础知识。通过本文您将学习如何:使用ASP.NET Core SignalR + MVC + Vue 2.x + require 最终创建一个正常运行的简易聊天应用。
废话不多说,我们直接来看一个Demo,Demo的目录结构如下所示:

本Demo的Web项目为ASP.NET Core Web 应用程序(目标框架为.NET 7.0) MVC项目。
1、创建 SignalR 中心
中心是一个类,用作处理客户端 - 服务器通信的高级管道。
可通过已连接客户端调用 SendMessage,以向所有客户端发送消息。- using Microsoft.AspNetCore.SignalR;
- namespace SignalRChat.Hubs
- {
- /// <summary>
- /// Hub 类管理连接、组和消息
- /// </summary>
- public class ChatHub : Hub
- {
- /// <summary>
- /// 可通过已连接客户端调用 SendMessage,以向所有客户端发送消息
- /// </summary>
- public async Task SendMessage(string user, string message)
- {
- //Clients.All 向所有的客户端发送消息(服务端调用客户端)
- //ReceiveMessage 是客户端监听的方法
- await Clients.All.SendAsync("ReceiveMessage", user, message);
- /*
- // 常用方法
- // 给所有人发送消息
- await Clients.All.SendAsync("ReceiveMessage", data);
- // 给组里所有人发消息
- await Clients.Group("Users").SendAsync("ReceiveMessage", data);
- // 给调用方法的那个人发消息
- await Clients.Caller.SendAsync("ReceiveMessage", data);
- // 给除了调用方法的以外所有人发消息
- await Clients.Others.SendAsync("ReceiveMessage", data);
- // 给指定connectionId的人发消息
- await Clients.User(connectionId).SendAsync("ReceiveMessage", data);
- // 给指定connectionId的人发消息
- await Clients.Client(connectionId).SendAsync("ReceiveMessage", data);
- // 给指定connectionId的人发消息,同时指定多个connectionId
- await Clients.Clients(IReadOnlyList<> connectionIds).SendAsync("ReceiveMessage", data);
- */
- }
- }
- }
复制代码 2、配置 SignalR
必须将 SignalR 服务器配置为将 SignalR 请求传递给 SignalR。 将以下突出显示(标红)的代码添加到 Program.cs 文件。- using SignalRChat.Hubs;
- namespace SignalRChat
- {
- public class Program
- {
- public static void Main(string[] args)
- {
- var builder = WebApplication.CreateBuilder(args);
- //服务注册(往容器中添加服务)
- // Add services to the container.
- builder.Services.AddControllersWithViews();
- builder.Services.AddSignalR(); //SignalR
- var app = builder.Build();
- //配置Http请求处理管道
- // Configure the HTTP request pipeline.
- if (!app.Environment.IsDevelopment())
- {
- app.UseExceptionHandler("/Home/Error");
- }
- app.UseStaticFiles();
- app.UseRouting();
- app.UseAuthorization();
- //配置MVC路由
- app.MapControllerRoute(
- name: "areas",
- pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
- app.MapControllerRoute(
- name: "default",
- pattern: "{controller=Home}/{action=Index}/{id?}");
- app.MapHub<ChatHub>("/chatHub"); //SignalR
- app.Run();
- }
- }
- }
复制代码 以上突出显示(标红)的代码将 SignalR 添加到 ASP.NET Core 依赖关系注入和路由系统。
3、添加 SignalR 客户端代码
chat.js 文件,核心 JavaScript 代码如下:- //第一个参数:加载依赖模块,可以是require_config中定义的短模块名,也可以是完整的模块路径(去掉.js后缀名,根目录为require_config中设置的baseUrl)
- //第二个参数:执行加载完后的回调函数
- require(['../common/base', 'jquery', 'signalr'], function (base, $, signalR) {
- let axios = base.axios;
- var vm = new base.vue({
- el: '#app', //挂载点
- mixins: [base.mixin], //混入,类似基类的概念
- data: {
- connectionSignalR: '', //SignalR连接
- user: '',
- message: '',
- msgList: []
- },
- //created钩子函数
- created: function () {
- this.initSignalR(); //初始化SignalR
- },
- //mounted钩子函数
- mounted: function () {
- //console.log('This is index mounted');
- },
- //方法
- methods: {
- //初始化SignalR
- initSignalR: function () {
- var _this = this;
- //创建连接
- _this.connectionSignalR = new signalR.HubConnectionBuilder()
- .withUrl("/chatHub")
- .configureLogging(signalR.LogLevel.Error)
- .build();
- /*
- 日志等级:
- signalR.LogLevel.Error:错误消息。 Error仅记录消息。
- signalR.LogLevel.Warning:有关潜在错误的警告消息。 日志 Warning 和 Error 消息。
- signalR.LogLevel.Information:无错误的状态消息。 日志 Information 、 Warning 和 Error 消息。
- signalR.LogLevel.Trace:跟踪消息。 记录所有内容,包括中心和客户端之间传输的数据。
- */
- //监听中心(服务端)发送的消息(服务端调用客户端)
- //ReceiveMessage 是服务端调用客户端的方法名
- _this.connectionSignalR.on("ReceiveMessage", function (user, message) {
- _this.msgList.push({
- user: user,
- message: message
- });
- });
- //启动连接
- _this.connectionSignalR.start().then(function () {
- //启动连接后需要立即执行的逻辑
- //document.getElementById("sendButton").disabled = false;
- }).catch(function (err) {
- return console.error(err.toString());
- });
- },
- //发送消息
- sendMsg: function () {
- var _this = this;
- if (_this.message) {
- //向中心(服务端)发送消息(客户端调用服务端)
- //SendMessage 是服务端定义的的方法
- _this.connectionSignalR.invoke("SendMessage", _this.user, _this.message).catch(function (err) {
- return console.error(err.toString());
- });
- _this.message = ''; //发送完清空消息
- }
- },
- }
- });
- });
复制代码 公共脚本文件代码如下:
其中 require_config.js 文件代码如下:- //主要用来配置模块的加载位置(设置短模块名)
- require.config({
- baseUrl: '/js/lib', //设置根目录
- paths: { //如果没有设置根目录则需要填写完整路径
- 'vue': 'vue',
- 'axios': 'axios',
- 'jquery': 'jquery-3.6.3',
- 'signalr': 'signalr',
- //paths还有一个重要的功能,就是可以配置多个路径,如果远程cdn库没有加载成功,可以加载本地的库,如下:
- //'jquery': ['http://libs.baidu.com/jquery/2.0.3/jquery', '/js/lib/jquery-3.6.3'],
- }
- });
复制代码 其中 base.js 文件代码如下:- //define用来自定义模块
- //第一个参数:加载依赖模块,可以是require_config中定义的短模块名,也可以是完整的模块路径(去掉.js后缀名)
- //第二个参数:执行加载完后的回调函数
- define(['vue', 'axios', '../components/buttonCounter'], function (vue, axios, buttonCounter) {
- //TODO 此处可以处理一些公共的逻辑
- //vue.component('component-a', { /* ... */ }); //全局注册组件
- //vue.mixin({...}); //全局混入
- /*
- 定义组件名的方式有两种:
- 1、使用 kebab-case (短横线分隔命名)
- 当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>
-
- 2、使用 PascalCase (首字母大写命名)
- 当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。
- 也就是说 <my-component-name> 和 <MyComponentName> 都是可接受的。
- 注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
- */
- //Vue.component(...) 的第一个参数为组件名。
- vue.component('button-counter', buttonCounter); //全局注册
- return {
- vue: vue,
- axios: axios,
- //Vue混入
- mixin: {
- //数据
- data: function () {
- return {
- domain: '', //域名
- }
- },
- //组件
- components: {
- },
- //created钩子函数
- created: function () {
- //console.log('This is base created');
- var _this = this;
- _this.getDomain();
- },
- //mounted钩子函数
- mounted: function () {
- console.log('This is base mounted');
- },
- //方法
- methods: {
- //测试
- doTest: function () {
- console.log('This is base doTest');
- },
- //获取域名
- getDomain: function () {
- var _this = this;
- _this.domain = 'http://localhost:5296';
- },
- }
- },
- };
- });
复制代码 控制器和视图文件代码如下:
其中 HomeController 控制器代码如下:- using Microsoft.AspNetCore.Mvc;
- using SignalRChat.Models;
- using System.Diagnostics;
- namespace SignalRChat.Controllers
- {
- public class HomeController : Controller
- {
- private readonly ILogger<HomeController> _logger;
- public HomeController(ILogger<HomeController> logger)
- {
- _logger = logger;
- }
- public IActionResult Index()
- {
- return View();
- }
- }
- }
复制代码 其中布局页 _Layout.cshtml 视图文件代码如下:- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>@ViewData["Title"] - SignalRChat</title>
-
-
- @await RenderSectionAsync("header", required: false)
- </head>
- <body>
-
- @RenderBody()
-
- @await RenderSectionAsync("footer", required: false)
- </body>
- </html>
复制代码 其中 Index.cshtml 视图文件代码如下:- @{
- ViewData["Title"] = "Home Page";
- }
- <template>
- <p>
- User:<input v-model="user" type="text" />
- </p>
- <p>
- Message: <input v-model="message" type="text" />
- </p>
- <p>
- <button v-on:click="sendMsg">发送</button>
- </p>
- <hr />
- <ul>
- <li v-for="(item, index) in msgList" :key="index">
- {{ item.user }} says {{ item.message }}
- </li>
- </ul>
- </template>
- @section footer{
-
- }
复制代码 4、运行应用
此处我使用的是 .NET Core CLI 命令行的方式来运行应用,如下所示:

打开两个浏览器实例,分别访问:http://localhost:5296/ , 运行结果如下:

选择任一浏览器,输入名称和消息,然后点击“发送”按钮:

可以发现,两个页面上会立即显示名称和消息。
更多关于 ASP.NET Core SignalR 的相关知识可参考微软官方文档:https://learn.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-7.0&tabs=visual-studio
至此本文就全部介绍完了,如果觉得对您有所启发请记得点个赞哦!!!
Demo源码:- 链接:https://pan.baidu.com/s/13ppUjr0h2dse5vnw5uiZ9Q
- 提取码:qm2a
复制代码 此文由博主精心撰写转载请保留此原文链接:https://www.cnblogs.com/xyh9039/p/17520659.html
版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |