SignalR实战,如何在.NET Framework和.NET Core中应用SignalR实现实时通信?

2026-03-30 22:241阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3452个文字,预计阅读时间需要14分钟。

官方文档:ASP.NET Core SignalR 入门 | Microsoft LearnSignalR开源代码:SignalR · GitHub常见问题:在前后端分离项目中,后端是.NET Core,前端是Vue,如何使用SignalR?在前后端不分离项目中,如何使用.NE

官网文档:ASP.NET Core SignalR 入门 | Microsoft Learn

SignalR开源代码:SignalR · GitHub


很多小伙伴问:在前后端分离项目中,后端是.NET Core前端是Vue如何使用SignalR?在前后端不分离项目中,.NET Framework MVC项目中又如何使用SignalR技术呢?那就来看看下面这篇文章吧!本文主要介绍SignalR在实际项目中的应用,以及.NET Framework和.NET Core中如何去使用SignalR。


一、SignalR介绍

1.1-SignalR介绍

ASP.NET Core SignalR是一个开放源代码库,可用于简化向应用添加实时Web功能,实时Web功能使服务器端代码能够将内容推送到客户端。


1.2-SignalR的应用

  • 需要从服务器进行高频更新的应用:包括游戏、社交网络、投票、拍卖、地图和GPS引用。
  • 仪表盘和监视应用:包括公司仪表板、即时销售更新或旅行报警
  • 协作应用:包括白板应用和团队会议软件。
  • 通知应用:社交网络、电子邮件、聊天、游戏、旅行报警和其他应用都需要使用的通知。


二、.NET Framework使用SignalR

参考文献:

Owin介绍:www.cnblogs.com/Pinapple/p/6721361.html

Owin相关案例:1. 第一个 Owin 程序_microsoft.owin_bifan546的博客-CSDN博客


2.1-服务端(.NET Framework MVC)

(1)选择要使用Signalr的项目,点击。


(2)搜索包,找到这个后然后点击下载。


会自动安装四个,注意他们之间有依赖关系:


(3).NET Framework平台需要添加Owin相关的包。

OWIN 是一种定义 Web 服务器和应用程序组件之间的交互的规范 。这一规范的目的是发展一个广阔且充满活力的、基于 Microsoft .NET Framework 的 Web 服务器和应用程序组件生态系统。

Microsoft.Owin.Hosting
Microsoft.Owin.Cors
Microsoft.Owin.Host.HttpListener


(4)在Web项目(要使用的Signal)中创建一个文件。

using JiCai.Admin.Hubs; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(JiCai.Admin.Startup))] namespace JiCai.Admin { public class Startup { /// <summary> /// 应用程序配置 /// </summary> /// <param name="app"></param> public void Configuration(IAppBuilder app) { //启用SignalR app.MapSignalR(); //绑定多个Hub app.MapSignalR<DemoHub>("/demoHub"); } } }

例如:

(5)可以创建一个文件夹,专门放置Hub相关文件。[西瓜程序猿]这边是创建一个Hub文件,名为。

using Fenqibao.DTO; using JiCai.Admin.Hubs.ConectionOperate; using JiCai.Admin.Hubs.Models; using log4net; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Json; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace JiCai.Admin.Hubs { /// <summary> /// 报表管理-总表Hub /// </summary> public class SummaryTableHub : PersistentConnection { public readonly BaseService _base = new BaseService(); private readonly ILog logger = LogManager.GetLogger(typeof(SummaryTableHub)); private ConnectionManagement summaryTableCon = new ConnectionManagement(); public CookieUserData LoginUserData { get { IOperator oper = ContainerManager.Resolve<IOperator>(); LoginUser loginUser = oper as LoginUser; if (loginUser != null && loginUser.UserData != null) { return loginUser.UserData; } return null; } } /// <summary> /// 连接成功后调用 /// </summary> /// <param name="request"></param> /// <param name="connectionId"></param> /// <returns></returns> protected override Task OnConnected(IRequest request, string connectionId) { //获得SignalR的连接id var connid = connectionId; //获得用户id var userid = LoginUserData.Id.ToString(); Console.Write($":已建立连接!"); //判断一下用户是不是已经链接了 var checkUserConn = summaryTableCon.IsConn(connid, userid); if (!checkUserConn) { //添加一个新的连接 summaryTableCon.AddConnInfo(new SignalRConn() { UserId = userid, ConnectionId = connid }); } //更新连接 else { summaryTableCon.UpdateConnInfo(userid, connid); } return Connection.Send(connectionId, $"真正连接成功!"); //return base.OnConnected(request, connectionId); } /// <summary> /// 接收到请求的时候调用 /// </summary> /// <param name="request"></param> /// <param name="connectionId"></param> /// <param name="data"></param> /// <returns></returns> protected override async Task OnReceived(IRequest request, string connectionId, string data) { //获得用户id var userid = LoginUserData.Id.ToString(); await Task.Factory.StartNew(async () => { while (true) { var list = GetSummaryTableList(userid); string json_jieshou_mes = ""; if (list != null && list.Count > 0) { json_jieshou_mes = JsonConvert.SerializeObject(list); } await Connection.Send(connectionId, json_jieshou_mes); //每5秒同步一次 await Task.Delay(5000); } }, TaskCreationOptions.LongRunning); //return base.OnReceived(request, connectionId, data); } /// <summary> /// 连接中断的时候调用 /// </summary> /// <param name="request"></param> /// <param name="connectionId"></param> /// <param name="stopCalled"></param> /// <returns></returns> protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled) { Console.Write($":已断开连接!"); //获得SignalR的连接id var connid = connectionId; //关闭连接 summaryTableCon.DelConnInfo(connid); return base.OnDisconnected(request, connectionId, stopCalled); } /// <summary> /// 连接超时重新连接的时候调用 /// </summary> /// <param name="request"></param> /// <param name="connectionId"></param> /// <returns></returns> protected override Task OnReconnected(IRequest request, string connectionId) { return base.OnReconnected(request, connectionId); } /// <summary> /// 查询数据 /// </summary> /// <param name="userId"></param> /// <returns></returns> private List<SummaryTableDataModel> GetSummaryTableList(string userId) { var result = _base.Query<SummaryTableDataModel>($@" select * from demo-data ; ").ToList(); return result; } } }

(6)在Hubs/ConectionOperate文件夹中,[西瓜程序猿]这边创建文件,用来管理所有连接。

using System.Collections.Generic; using System.Linq; namespace JiCai.Admin.Hubs.ConectionOperate { /// <summary> /// 连接管理 /// </summary> public class ConnectionManagement { /// <summary> /// 用户连接集合 /// </summary> public static List<SignalRConn> SignalRConns { get; set; } = new List<SignalRConn>(); /// <summary> /// 添加连接 /// </summary> /// <param name="conn"></param> public void AddConnInfo(SignalRConn conn) { SignalRConns.Add(conn); } /// <summary> /// 删除连接 /// </summary> /// <param name="connid"></param> public void DelConnInfo(string connid) { var signalRConns = SignalRConns.FirstOrDefault(u => u.ConnectionId == connid); if (signalRConns != null) { SignalRConns.Remove(signalRConns); } } /// <summary> /// 更新链接(老的链接不起作用了) /// 场景:客户端重连了,userid没变,但是connid变了 /// </summary> /// <param name="userId">用户id</param> /// <param name="newConnsId">新的链接id</param> public void UpdateConnInfo(string userId, string newConnsId) { var signalRConns = SignalRConns.FirstOrDefault(u => u.UserId.ToLower() == userId.ToLower()); if (signalRConns != null) { signalRConns.ConnectionId = newConnsId; } } /// <summary> /// 判断用户是否已经链接 /// </summary> /// <param name="connid">连接id</param> /// <param name="userid">用户id</param> /// <returns></returns> public bool IsConn(string connid,string userid) { var userConn = SignalRConns.FirstOrDefault(u => u.ConnectionId.ToLower() == connid.ToLower() && u.UserId.ToLower() == userid.ToLower()); return userConn == null ? false : true; } } }

(7)在Hubs/ConectionOperate文件夹中,创建文件用来作为SignalR和系统用户的连接实体。

namespace JiCai.Admin.Hubs.ConectionOperate { /// <summary> /// 连接 /// </summary> public class SignalRConn { /// <summary> /// 系统用户id /// </summary> public string UserId { get; set; } /// <summary> /// SignleR链接Id(每次链接SignalR都会分配一个id) /// </summary> public string ConnectionId { get; set; } } }


2.2-客户端(JS)

(1)下载相关jq/signalr相关包,分别是和。可以访问下载(如果失效了,请联系我[西瓜程序猿])。

下载地址(编码:yRLCRp81):yongteng.lanzoub.com/iXDlu1631ugd
密码:44x5

文件截图:

(2)创建一个js文件,用来连接signalR。

// 连接服务 var connection = $.connection("/summary_table_hub"); // 建立链接 connection.start(function () { //连接成功 console.log("西瓜程序猿-连接成功!"); //发送消息 connection.send("给我数据吧"); }); // 连接断开 connection.disconnected(function () { console.log("西瓜程序猿-连接断开!"); }); // 接收服务器发来的消息 connection.received(function (data) { console.log("西瓜程序猿-接收服务器发来的消息:"); console.log(data); //显示数据 if (data != "" && checkJson(data)) { var obj = JSON.parse(data); var html_box = ""; for (var i = 0; i < obj.length; i++) { html_box += `<tr> <td>`+obj[i].project_name+`</td> <td>`+ obj[i].zuori_sum+`</td> <td>`+ obj[i].jinri_sum+`</td> <td>`+ obj[i].qunian_sum+`</td> <td>`+ obj[i].jinnian_sum+`</td> <td>`+ obj[i].sum+`</td> <td>`+ obj[i].yikaipiao_sum+`</td> <td>`+ obj[i].weikaipiao_sum +`</td> <td>`+ obj[i].yishoupiao_sum +`</td> <td>`+ obj[i].weishoupiao_sum +`</td> <td>`+ obj[i].kehu_yinghuikuan_sum+`</td> <td>`+ obj[i].kehu_yihuikuan_sum+`</td> <td>`+ obj[i].kehu_weihuikuan_sum +`</td> <td>`+ obj[i].fuwu_yingfukuan_sum+`</td> <td>`+ obj[i].fuwu_yifukuan_sum+`</td> <td>`+ obj[i].fuwu_weifukuan_sum+`</td> </tr>` } $("#last_async_date").text(new Date().toLocaleString()); $("#table_body").html(html_box); } }); //判断是不是json字符串 function checkJson(str) { if (typeof str == 'string') { try { var obj = JSON.parse(str); // 等于这个条件说明就是JSON字符串 会返回true if (typeof obj == 'object' && obj) { return true; } else { //不是就返回false return false; } } catch (e) { return false; } } return false; }

(3)创建要展示的文件,我这边是用MVC模式,所有前台文件是cshtml。

@{ ViewBag.Title = "西瓜程序猿-明细表"; } @section styles{ <style> .table_tr_center { text-align: center !important; } .table_tr_bg_0 { background: rgb(253,226,226); } .table_tr_bg_1 { background: rgb(218,226,246); } .table_tr_bg_2 { background: rgb(228,237,219); } .table_tr_bg_3 { background: rgb(249,229,215); } </style> } @section scripts{ <script src="~/Scripts/jquery-1.6.4.min.js"></script> <script src="~/Scripts/jquery.signalR-2.4.3.js"></script> <script src="~/Scripts/controller/hubs/data_list_table_hub.js?v=@DateTime.Now.Ticks"></script> } <div class="row"> <div class="col-xs-12"> </div> <div class="col-xs-12"> <div> 报表最新同步时间:<span id="last_async_date" style="color: #FF5722 !important;"></span> </div> <div class="layui-form"> <table class="layui-table"> <colgroup> <col> <col> <col> <col> <col> <col> <col> <col> <col> <col> <col> <col> <col> </colgroup> <thead> <tr> <th colspan="2" class="table_tr_center table_tr_bg_0">项目信息</th> <th colspan="5" class="table_tr_center table_tr_bg_1">销售情况</th> <th colspan="6" class="table_tr_center table_tr_bg_3">款项情况</th> </tr> <tr> <th class="table_tr_center">项目名称</th> <th class="table_tr_center">服务商名称</th> <th class="table_tr_center">昨天订单总额</th> <th class="table_tr_center">今天订单总额</th> <th class="table_tr_center">去年订单总额</th> <th class="table_tr_center">今年订单总额</th> <th class="table_tr_center">订单总额</th> <th class="table_tr_center">客户应回款总额</th> <th class="table_tr_center">客户已回款总额</th> <th class="table_tr_center">客户未回款总额</th> <th class="table_tr_center">服务商应付款总额</th> <th class="table_tr_center">服务商已付款总额</th> <th class="table_tr_center">服务商未付款总额</th> </tr> </thead> <tbody id="table_body"> </tbody> </table> </div> </div> </div>


(4)效果展示:


三、.NET Core WebAPI使用SignalR

场景:项目中需要服务端主动向客户端发送通知消息,后端是使用.NETCore实现的,前端是使用Vue3全家桶项目,前后端分离模式。本次主要讲使用SignalR如何来实现的。


3.1-服务端(.NET Core WebAPI)

1、右击项目,点击安装SignalR。


2、搜索,点击。


3、如果是.NET6以前的版本,在中配置:

如果是.NET6以后得版本,在配置:

var builder = WebApplication.CreateBuilder(args); //添加SignalR服务 builder.Services.AddSignalR(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}" ); //添加SignalR端点 endpoints.MapHub<ServerMonitorHub>("/serverMonitorHub"); });

4、创建SignalR中心

中心是一个类,用于处理客户端<——>服务器通信的高级管道。在SignalR_Demo项目文件夹中,创建Hubs文件夹。在Hubs文件夹中,使用已下代码创建ChatHub类。

public class ChatHub:Hub { /// <summary> /// 发送消息 /// </summary> /// <param name="user">用户名</param> /// <param name="message">发送信息</param> /// <returns></returns> public async Task SendMessage(string user,string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } }


3.2-客户端(Vue3+Vite+TS)

(1)安装SugbalR

npm install @latelier/vue-signalr

版本截图:

(2)然后新建一个文件,用来封装业务逻辑相关代码。[西瓜程序猿]是在目录下,创建了一个名为的文件,也可以是js文件,根据自己项目的需要去新建。

代码:

import * as signalR from '@microsoft/signalr'; //如果需要身份验证 //.withUrl('/messageHub', {accessTokenFactory: () => sessionStorage.getItem('token')}) let connection; // 建立连接 async function start(url) { try { connection = new signalR.HubConnectionBuilder() .withUrl(url)//跨域需要使用绝对地址 .configureLogging(signalR.LogLevel.Information) .withAutomaticReconnect() // 设置自动重连机制 .build(); } catch(err) { console.log(err); setTimeout(start, 10000);//错误重连 } } // 开始signalr连接 const connect = async (url) => { await start(url); console.log(`:从服务器同步成功!`); if(res) { const result = JSON.parse(res); getServerInfos(result); } }); // 开始连接 await connection.start(); }); // 卸载 onBeforeUnmount(() => { // 断开连接 disconnect(); }); // 进度条颜色 const customColor = ref('#ff7831'); </script> <style lang="scss" scoped> .card-box { padding-right: 15px; margin-bottom: 15px; } :deep(.el-card.is-always-shadow) { box-shadow: 0 5px 8px 0 rgba(0,0,0,0.03); border: none; } .chart { width: 100%; height: 300px; } .box_item { display: flex; justify-content: center; flex-direction: column; align-items: center; } .table_tbody { tr td{ padding: 15px 0; text-align: center; } } </style>

(5)效果展示:



版权声明:本文为原创文章,版权归 [西瓜程序猿] 所有,转载请注明出处,有任何疑问请私信咨询。

原文链接:blog.51cto.com/kimiliucn/7194470


本文共计3452个文字,预计阅读时间需要14分钟。

官方文档:ASP.NET Core SignalR 入门 | Microsoft LearnSignalR开源代码:SignalR · GitHub常见问题:在前后端分离项目中,后端是.NET Core,前端是Vue,如何使用SignalR?在前后端不分离项目中,如何使用.NE

官网文档:ASP.NET Core SignalR 入门 | Microsoft Learn

SignalR开源代码:SignalR · GitHub


很多小伙伴问:在前后端分离项目中,后端是.NET Core前端是Vue如何使用SignalR?在前后端不分离项目中,.NET Framework MVC项目中又如何使用SignalR技术呢?那就来看看下面这篇文章吧!本文主要介绍SignalR在实际项目中的应用,以及.NET Framework和.NET Core中如何去使用SignalR。


一、SignalR介绍

1.1-SignalR介绍

ASP.NET Core SignalR是一个开放源代码库,可用于简化向应用添加实时Web功能,实时Web功能使服务器端代码能够将内容推送到客户端。


1.2-SignalR的应用

  • 需要从服务器进行高频更新的应用:包括游戏、社交网络、投票、拍卖、地图和GPS引用。
  • 仪表盘和监视应用:包括公司仪表板、即时销售更新或旅行报警
  • 协作应用:包括白板应用和团队会议软件。
  • 通知应用:社交网络、电子邮件、聊天、游戏、旅行报警和其他应用都需要使用的通知。


二、.NET Framework使用SignalR

参考文献:

Owin介绍:www.cnblogs.com/Pinapple/p/6721361.html

Owin相关案例:1. 第一个 Owin 程序_microsoft.owin_bifan546的博客-CSDN博客


2.1-服务端(.NET Framework MVC)

(1)选择要使用Signalr的项目,点击。


(2)搜索包,找到这个后然后点击下载。


会自动安装四个,注意他们之间有依赖关系:


(3).NET Framework平台需要添加Owin相关的包。

OWIN 是一种定义 Web 服务器和应用程序组件之间的交互的规范 。这一规范的目的是发展一个广阔且充满活力的、基于 Microsoft .NET Framework 的 Web 服务器和应用程序组件生态系统。

Microsoft.Owin.Hosting
Microsoft.Owin.Cors
Microsoft.Owin.Host.HttpListener


(4)在Web项目(要使用的Signal)中创建一个文件。

using JiCai.Admin.Hubs; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(JiCai.Admin.Startup))] namespace JiCai.Admin { public class Startup { /// <summary> /// 应用程序配置 /// </summary> /// <param name="app"></param> public void Configuration(IAppBuilder app) { //启用SignalR app.MapSignalR(); //绑定多个Hub app.MapSignalR<DemoHub>("/demoHub"); } } }

例如:

(5)可以创建一个文件夹,专门放置Hub相关文件。[西瓜程序猿]这边是创建一个Hub文件,名为。

using Fenqibao.DTO; using JiCai.Admin.Hubs.ConectionOperate; using JiCai.Admin.Hubs.Models; using log4net; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Json; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace JiCai.Admin.Hubs { /// <summary> /// 报表管理-总表Hub /// </summary> public class SummaryTableHub : PersistentConnection { public readonly BaseService _base = new BaseService(); private readonly ILog logger = LogManager.GetLogger(typeof(SummaryTableHub)); private ConnectionManagement summaryTableCon = new ConnectionManagement(); public CookieUserData LoginUserData { get { IOperator oper = ContainerManager.Resolve<IOperator>(); LoginUser loginUser = oper as LoginUser; if (loginUser != null && loginUser.UserData != null) { return loginUser.UserData; } return null; } } /// <summary> /// 连接成功后调用 /// </summary> /// <param name="request"></param> /// <param name="connectionId"></param> /// <returns></returns> protected override Task OnConnected(IRequest request, string connectionId) { //获得SignalR的连接id var connid = connectionId; //获得用户id var userid = LoginUserData.Id.ToString(); Console.Write($":已建立连接!"); //判断一下用户是不是已经链接了 var checkUserConn = summaryTableCon.IsConn(connid, userid); if (!checkUserConn) { //添加一个新的连接 summaryTableCon.AddConnInfo(new SignalRConn() { UserId = userid, ConnectionId = connid }); } //更新连接 else { summaryTableCon.UpdateConnInfo(userid, connid); } return Connection.Send(connectionId, $"真正连接成功!"); //return base.OnConnected(request, connectionId); } /// <summary> /// 接收到请求的时候调用 /// </summary> /// <param name="request"></param> /// <param name="connectionId"></param> /// <param name="data"></param> /// <returns></returns> protected override async Task OnReceived(IRequest request, string connectionId, string data) { //获得用户id var userid = LoginUserData.Id.ToString(); await Task.Factory.StartNew(async () => { while (true) { var list = GetSummaryTableList(userid); string json_jieshou_mes = ""; if (list != null && list.Count > 0) { json_jieshou_mes = JsonConvert.SerializeObject(list); } await Connection.Send(connectionId, json_jieshou_mes); //每5秒同步一次 await Task.Delay(5000); } }, TaskCreationOptions.LongRunning); //return base.OnReceived(request, connectionId, data); } /// <summary> /// 连接中断的时候调用 /// </summary> /// <param name="request"></param> /// <param name="connectionId"></param> /// <param name="stopCalled"></param> /// <returns></returns> protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled) { Console.Write($":已断开连接!"); //获得SignalR的连接id var connid = connectionId; //关闭连接 summaryTableCon.DelConnInfo(connid); return base.OnDisconnected(request, connectionId, stopCalled); } /// <summary> /// 连接超时重新连接的时候调用 /// </summary> /// <param name="request"></param> /// <param name="connectionId"></param> /// <returns></returns> protected override Task OnReconnected(IRequest request, string connectionId) { return base.OnReconnected(request, connectionId); } /// <summary> /// 查询数据 /// </summary> /// <param name="userId"></param> /// <returns></returns> private List<SummaryTableDataModel> GetSummaryTableList(string userId) { var result = _base.Query<SummaryTableDataModel>($@" select * from demo-data ; ").ToList(); return result; } } }

(6)在Hubs/ConectionOperate文件夹中,[西瓜程序猿]这边创建文件,用来管理所有连接。

using System.Collections.Generic; using System.Linq; namespace JiCai.Admin.Hubs.ConectionOperate { /// <summary> /// 连接管理 /// </summary> public class ConnectionManagement { /// <summary> /// 用户连接集合 /// </summary> public static List<SignalRConn> SignalRConns { get; set; } = new List<SignalRConn>(); /// <summary> /// 添加连接 /// </summary> /// <param name="conn"></param> public void AddConnInfo(SignalRConn conn) { SignalRConns.Add(conn); } /// <summary> /// 删除连接 /// </summary> /// <param name="connid"></param> public void DelConnInfo(string connid) { var signalRConns = SignalRConns.FirstOrDefault(u => u.ConnectionId == connid); if (signalRConns != null) { SignalRConns.Remove(signalRConns); } } /// <summary> /// 更新链接(老的链接不起作用了) /// 场景:客户端重连了,userid没变,但是connid变了 /// </summary> /// <param name="userId">用户id</param> /// <param name="newConnsId">新的链接id</param> public void UpdateConnInfo(string userId, string newConnsId) { var signalRConns = SignalRConns.FirstOrDefault(u => u.UserId.ToLower() == userId.ToLower()); if (signalRConns != null) { signalRConns.ConnectionId = newConnsId; } } /// <summary> /// 判断用户是否已经链接 /// </summary> /// <param name="connid">连接id</param> /// <param name="userid">用户id</param> /// <returns></returns> public bool IsConn(string connid,string userid) { var userConn = SignalRConns.FirstOrDefault(u => u.ConnectionId.ToLower() == connid.ToLower() && u.UserId.ToLower() == userid.ToLower()); return userConn == null ? false : true; } } }

(7)在Hubs/ConectionOperate文件夹中,创建文件用来作为SignalR和系统用户的连接实体。

namespace JiCai.Admin.Hubs.ConectionOperate { /// <summary> /// 连接 /// </summary> public class SignalRConn { /// <summary> /// 系统用户id /// </summary> public string UserId { get; set; } /// <summary> /// SignleR链接Id(每次链接SignalR都会分配一个id) /// </summary> public string ConnectionId { get; set; } } }


2.2-客户端(JS)

(1)下载相关jq/signalr相关包,分别是和。可以访问下载(如果失效了,请联系我[西瓜程序猿])。

下载地址(编码:yRLCRp81):yongteng.lanzoub.com/iXDlu1631ugd
密码:44x5

文件截图:

(2)创建一个js文件,用来连接signalR。

// 连接服务 var connection = $.connection("/summary_table_hub"); // 建立链接 connection.start(function () { //连接成功 console.log("西瓜程序猿-连接成功!"); //发送消息 connection.send("给我数据吧"); }); // 连接断开 connection.disconnected(function () { console.log("西瓜程序猿-连接断开!"); }); // 接收服务器发来的消息 connection.received(function (data) { console.log("西瓜程序猿-接收服务器发来的消息:"); console.log(data); //显示数据 if (data != "" && checkJson(data)) { var obj = JSON.parse(data); var html_box = ""; for (var i = 0; i < obj.length; i++) { html_box += `<tr> <td>`+obj[i].project_name+`</td> <td>`+ obj[i].zuori_sum+`</td> <td>`+ obj[i].jinri_sum+`</td> <td>`+ obj[i].qunian_sum+`</td> <td>`+ obj[i].jinnian_sum+`</td> <td>`+ obj[i].sum+`</td> <td>`+ obj[i].yikaipiao_sum+`</td> <td>`+ obj[i].weikaipiao_sum +`</td> <td>`+ obj[i].yishoupiao_sum +`</td> <td>`+ obj[i].weishoupiao_sum +`</td> <td>`+ obj[i].kehu_yinghuikuan_sum+`</td> <td>`+ obj[i].kehu_yihuikuan_sum+`</td> <td>`+ obj[i].kehu_weihuikuan_sum +`</td> <td>`+ obj[i].fuwu_yingfukuan_sum+`</td> <td>`+ obj[i].fuwu_yifukuan_sum+`</td> <td>`+ obj[i].fuwu_weifukuan_sum+`</td> </tr>` } $("#last_async_date").text(new Date().toLocaleString()); $("#table_body").html(html_box); } }); //判断是不是json字符串 function checkJson(str) { if (typeof str == 'string') { try { var obj = JSON.parse(str); // 等于这个条件说明就是JSON字符串 会返回true if (typeof obj == 'object' && obj) { return true; } else { //不是就返回false return false; } } catch (e) { return false; } } return false; }

(3)创建要展示的文件,我这边是用MVC模式,所有前台文件是cshtml。

@{ ViewBag.Title = "西瓜程序猿-明细表"; } @section styles{ <style> .table_tr_center { text-align: center !important; } .table_tr_bg_0 { background: rgb(253,226,226); } .table_tr_bg_1 { background: rgb(218,226,246); } .table_tr_bg_2 { background: rgb(228,237,219); } .table_tr_bg_3 { background: rgb(249,229,215); } </style> } @section scripts{ <script src="~/Scripts/jquery-1.6.4.min.js"></script> <script src="~/Scripts/jquery.signalR-2.4.3.js"></script> <script src="~/Scripts/controller/hubs/data_list_table_hub.js?v=@DateTime.Now.Ticks"></script> } <div class="row"> <div class="col-xs-12"> </div> <div class="col-xs-12"> <div> 报表最新同步时间:<span id="last_async_date" style="color: #FF5722 !important;"></span> </div> <div class="layui-form"> <table class="layui-table"> <colgroup> <col> <col> <col> <col> <col> <col> <col> <col> <col> <col> <col> <col> <col> </colgroup> <thead> <tr> <th colspan="2" class="table_tr_center table_tr_bg_0">项目信息</th> <th colspan="5" class="table_tr_center table_tr_bg_1">销售情况</th> <th colspan="6" class="table_tr_center table_tr_bg_3">款项情况</th> </tr> <tr> <th class="table_tr_center">项目名称</th> <th class="table_tr_center">服务商名称</th> <th class="table_tr_center">昨天订单总额</th> <th class="table_tr_center">今天订单总额</th> <th class="table_tr_center">去年订单总额</th> <th class="table_tr_center">今年订单总额</th> <th class="table_tr_center">订单总额</th> <th class="table_tr_center">客户应回款总额</th> <th class="table_tr_center">客户已回款总额</th> <th class="table_tr_center">客户未回款总额</th> <th class="table_tr_center">服务商应付款总额</th> <th class="table_tr_center">服务商已付款总额</th> <th class="table_tr_center">服务商未付款总额</th> </tr> </thead> <tbody id="table_body"> </tbody> </table> </div> </div> </div>


(4)效果展示:


三、.NET Core WebAPI使用SignalR

场景:项目中需要服务端主动向客户端发送通知消息,后端是使用.NETCore实现的,前端是使用Vue3全家桶项目,前后端分离模式。本次主要讲使用SignalR如何来实现的。


3.1-服务端(.NET Core WebAPI)

1、右击项目,点击安装SignalR。


2、搜索,点击。


3、如果是.NET6以前的版本,在中配置:

如果是.NET6以后得版本,在配置:

var builder = WebApplication.CreateBuilder(args); //添加SignalR服务 builder.Services.AddSignalR(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}" ); //添加SignalR端点 endpoints.MapHub<ServerMonitorHub>("/serverMonitorHub"); });

4、创建SignalR中心

中心是一个类,用于处理客户端<——>服务器通信的高级管道。在SignalR_Demo项目文件夹中,创建Hubs文件夹。在Hubs文件夹中,使用已下代码创建ChatHub类。

public class ChatHub:Hub { /// <summary> /// 发送消息 /// </summary> /// <param name="user">用户名</param> /// <param name="message">发送信息</param> /// <returns></returns> public async Task SendMessage(string user,string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } }


3.2-客户端(Vue3+Vite+TS)

(1)安装SugbalR

npm install @latelier/vue-signalr

版本截图:

(2)然后新建一个文件,用来封装业务逻辑相关代码。[西瓜程序猿]是在目录下,创建了一个名为的文件,也可以是js文件,根据自己项目的需要去新建。

代码:

import * as signalR from '@microsoft/signalr'; //如果需要身份验证 //.withUrl('/messageHub', {accessTokenFactory: () => sessionStorage.getItem('token')}) let connection; // 建立连接 async function start(url) { try { connection = new signalR.HubConnectionBuilder() .withUrl(url)//跨域需要使用绝对地址 .configureLogging(signalR.LogLevel.Information) .withAutomaticReconnect() // 设置自动重连机制 .build(); } catch(err) { console.log(err); setTimeout(start, 10000);//错误重连 } } // 开始signalr连接 const connect = async (url) => { await start(url); console.log(`:从服务器同步成功!`); if(res) { const result = JSON.parse(res); getServerInfos(result); } }); // 开始连接 await connection.start(); }); // 卸载 onBeforeUnmount(() => { // 断开连接 disconnect(); }); // 进度条颜色 const customColor = ref('#ff7831'); </script> <style lang="scss" scoped> .card-box { padding-right: 15px; margin-bottom: 15px; } :deep(.el-card.is-always-shadow) { box-shadow: 0 5px 8px 0 rgba(0,0,0,0.03); border: none; } .chart { width: 100%; height: 300px; } .box_item { display: flex; justify-content: center; flex-direction: column; align-items: center; } .table_tbody { tr td{ padding: 15px 0; text-align: center; } } </style>

(5)效果展示:



版权声明:本文为原创文章,版权归 [西瓜程序猿] 所有,转载请注明出处,有任何疑问请私信咨询。

原文链接:blog.51cto.com/kimiliucn/7194470