ASP.NET Core SignalR 入门

  • ASP.NET Core SignalR 入门已关闭评论
  • 124 次浏览
  • A+
所属分类:.NET技术
摘要

本章将和大家分享使用 SignalR 生成实时应用的基础知识。通过本文您将学习如何:使用ASP.NET Core SignalR + MVC + Vue 2.x + require 最终创建一个正常运行的简易聊天应用。

本章将和大家分享使用 SignalR 生成实时应用的基础知识。通过本文您将学习如何:使用ASP.NET Core SignalR + MVC + Vue 2.x + require 最终创建一个正常运行的简易聊天应用。

废话不多说,我们直接来看一个Demo,Demo的目录结构如下所示:

ASP.NET Core SignalR 入门

本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  命令行的方式来运行应用,如下所示:

ASP.NET Core SignalR 入门

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

ASP.NET Core SignalR 入门

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

ASP.NET Core SignalR 入门

可以发现,两个页面上会立即显示名称和消息。 

更多关于 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

版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!