- A+
本章将和大家分享使用 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> <script src="/js/lib/require.js"></script> <script src="/js/common/require_config.js"></script> @await RenderSectionAsync("header", required: false) </head> <body> <div class="container"> @RenderBody() </div> @await RenderSectionAsync("footer", required: false) </body> </html>
其中 Index.cshtml 视图文件代码如下:
@{ ViewData["Title"] = "Home Page"; } <div id="app"> <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> </div> @section footer{ <script src="/js/pageScript/chat.js"></script> }
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
版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!