什么是 SignalR ASP.NET Core

ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能。 实时 web 功能使服务器端代码可以立即将内容推送到客户端。

SignalR ASP.NET Core可以做什么

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

SignalR  ASP.NET Core特色

• 自动处理连接管理。
• 可将消息同时发送到所有连接的客户端。
• 可向特定客户端或客户端组发送消息。
• 可缩放以处理不断增加的流量。
• SignalR采用rpc来进行客户端与服务器端之间的通信。
• SignalR会自动选择服务器和客户端的最佳传输方法(WebSockets、Server-Sent事件、长轮询)SignalR可以根据当前浏览器所支持的协议来选择最优的连接方式,从而可以让我们把更多的精力放在业务上而不是底层传输技术上。

哪些浏览器支持SignalR  ASP.NET Core

Apple Safari(包含IOS端)、Google Chrome(包括 Android端)、Microsoft Edge、Mozilla Firefox等主流浏览器都支持SignalR  ASP.NET Core。

本次我们将实现一个通过SignalR来简单实现一个后台实时推送数据给Echarts来展示图表的功能

首先我们新建一个ASP.NET Core 3.1的web应用

随后我们引用SignalR  ASP.NET Core、Jquery和Echarts的客户端库

在项目中我们新建以下目录

Class、HubInterface、Hubs

接着我们在Pages目录下新建如下目录

echarts

在Shared目录中新建一个Razor布局页(_LayoutEcharts.cshtml)

在echarts目录中新建一个Razor页面(Index.cshtml)

在Class目录中新建一个类(ClientMessageModel.cs)

在HubInterface目录中新建一个接口(IChatClient.cs)

在Hub目录中新建一个类(ChatHub.cs)

我们先实现后台逻辑代码,随后在编写前端交互代码。

在IChatClient.cs中,我们主要是定义统一的服务端调用客户端方法的统一方法名(防止每次都要手动输入调用方法是出现失误而导致调用失败的低级错误)

namespace signalr.HubInterface
{public interface IChatClient{/// <summary>/// 客户端接收数据触发函数名/// </summary>/// <param name="clientMessageModel">消息实体类</param>/// <returns></returns>Task ReceiveMessage(ClientMessageModel clientMessageModel);/// <summary>/// Echart接收数据触发函数名/// </summary>/// <param name="data">JSON格式的可以被Echarts识别的data数据</param>/// <returns></returns>Task EchartsMessage(Array data);/// <summary>/// 客户端获取自己登录后的UID/// </summary>/// <param name="clientMessageModel">消息实体类</param>/// <returns></returns>Task GetMyId(ClientMessageModel clientMessageModel);}
}

ClientMessageModel.cs中,我们主要定义的是序列化后的交互用的实体类

namespace signalr.Class
{/// <summary>/// 服务端发送给客户端的信息/// </summary>[Serializable]public class ClientMessageModel{/// <summary>/// 接收用户编号/// </summary>public string UserId { get; set; }/// <summary>/// 组编号/// </summary>public string GroupName { get; set; }/// <summary>/// 发送的内容/// </summary>public string Context { get; set; }}
}

在ChatHub.cs中,主要是实现SignalR集线器的核心功能,用来处理客户端<==>服务器交互代码。在这里我们继承了Hub<T>的方法,集成了我们定义的IChatClient接口,从而就可以在方法中直接调用接口名称来和客户端交互。

namespace signalr.Hubs
{public class ChatHub : Hub<IChatClient>{public override async Task OnConnectedAsync(){var user = Context.ConnectionId;await Clients.Client(user).GetMyId(new ClientMessageModel { UserId = user, Context = $"回来了{DateTime.Now:yyyy-MM:dd HH:mm:ss}" });await Clients.AllExcept(user).ReceiveMessage(new ClientMessageModel { UserId = user, Context = $"进来了{DateTime.Now:yyyy-MM:dd HH:mm:ss}" });await base.OnConnectedAsync();}public override async Task OnDisconnectedAsync(Exception exception){var user = Context.ConnectionId;await Clients.All.ReceiveMessage(new ClientMessageModel { UserId = user, Context = $"{user}离开了{DateTime.Now:yyyy-MM:dd HH:mm:ss}" });await base.OnDisconnectedAsync(exception);}}
}

我们重写了Hub的OnConnectedAsync方法,当有客户端连接进来的时候,我们给当前客户端发送一条“回来了”的内容,同时给所有在线的客户端发送一条“进来了”的通知,内容中会带上本次连接所分配给动态Guid编号。(类似与通知大家谁谁上线了)

在OnDisconnectedAsync方法中,当客户端断开连接的时候,会给所有在线客户端发送一条带有离线客户端的Guid的离开消息。(类似通知大家谁谁谁离开了)

在Startup.cs中,我们做以下设置(注入SignalR和注册Hub),同时先把在DEBUG模式下的XSRF禁用,否则访问接口会提示400错误

public void ConfigureServices(IServiceCollection services){services.AddSignalR();services.AddRazorPages()
#if DEBUG//Debug下禁用XSRF防护,方便调试.AddRazorPagesOptions(o =>{o.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute());})
#endif;}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Error");}app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapRazorPages();endpoints.MapHub<ChatHub>("/chathub");//注册hub});} 

以上服务端的基架功能就搭建好了,下面我们会来实现后台推送数据给前台Echart的功能。

在_LayoutEcharts.cshtml布局页中,我们实现引用Jquery和Echarts的JS文件,同时编写一个请求后台接口的方法,调用这个方法后,后台就会主动推送多次数据给前台。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width" /><script src="~/lib/echarts/dist/echarts.min.js"></script><script src="~/lib/jquery/dist/jquery.js"></script><title>@ViewBag.Title</title><script>function Test() {var chartDom = document.getElementById('main');var myChart = window.echarts.init(chartDom);$.ajax({url:'/echarts',type:'POST',dateType: 'json',data: { user: user},beforeSend: function (XHR) {console.log('I am ' + user);myChart.showLoading({text: '加载中。。。',effect: 'whirling'});},success:function(data) {var option = {series: [{data: data.data}]};myChart.setOption(option);},error: function (XMLHttpRequest, textStatus, errorThrown) {alert(errorThrown);},complete:function(XHR, TS) {myChart.hideLoading();}});}</script>
</head>
<body>
<div>@RenderBody()
</div>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>

在echarts目录的Index.cshtml中,我们实现引用Echarts组件,来渲染图表,引用SignalR来实现和服务器端数据实时交互。

@page
@model signalr.Pages.echarts.IndexModel
@{ViewBag.Title = "Echarts图标展示(https://www.cnblogs.com/wdw984)";Layout = "_LayoutEcharts";
}<div id="main" style="width: 800px;height:600px;"></div>
<button onclick="Test()">测试</button>
<script type="text/javascript">
var app = {};var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
var option;var posList = ['left', 'right', 'top', 'bottom','inside','insideTop', 'insideLeft', 'insideRight', 'insideBottom','insideTopLeft', 'insideTopRight', 'insideBottomLeft', 'insideBottomRight'
];app.configParameters = {rotate: {min: -90,max: 90},align: {options: {left: 'left',center: 'center',right: 'right'}},verticalAlign: {options: {top: 'top',middle: 'middle',bottom: 'bottom'}},position: {options: posList.reduce(function (map, pos) {map[pos] = pos;return map;}, {})},distance: {min: 0,max: 100}
};
app.config = {rotate: -25,align: 'left',verticalAlign: 'middle',position: 'bottom',distance: 15,onChange: function () {var labelOption = {normal: {rotate: app.config.rotate,align: app.config.align,verticalAlign: app.config.verticalAlign,position: app.config.position,distance: app.config.distance}};myChart.setOption({series: [{label: labelOption}, {label: labelOption}, {label: labelOption}, {label: labelOption}]});}
};
var labelOption = {show: true,position: app.config.position,distance: app.config.distance,align: app.config.align,verticalAlign: app.config.verticalAlign,rotate: app.config.rotate,formatter: '{c}  {name|{a}}',fontSize: 16,rich: {name: {}}
};option = {title: {text: '验证情况统计'},tooltip: {},legend: {},xAxis: {data: ['数据一','数据二', '数据三','','数据四', '数据五','','数据六', '数据七', '数据八','数据九','','数据十','数据十一','数据十二','数据十三','数据十四'],axisTick: {show: false},axisLabel:{rotate: -25,interval: 0}},yAxis: {},series: [{type: 'bar',label: {show: true,position: 'outside'},itemStyle: {normal: {               color: function(params) {var colorList = ["Blue","Blue","Blue","","LightSkyBlue","LightSkyBlue","","Gold","Gold","Gold","Gold","","LightGrey","LightGrey","LightGrey","LightGrey","LightGrey"];return colorList[params.dataIndex];}}},data: ['0','0','0','', '0', '0', '', '0','0','0','0','', '0','0','0','0','0']}]
};option && myChart.setOption(option);</script>
@section Scripts
{<script src="~/js/signalr/dist/browser/signalr.js"></script><script src="~/js/echartchat.js"></script>
}

在Index后台代码中,我们响应一个POST请求,请求中带上SignalR分配的唯一编号,后台模拟数据统计,推送给前台,这里用Task.Factory来创建一个任务执行这个操作。

private readonly IHubContext<ChatHub, IChatClient> _hubContext;public IndexModel(IHubContext<ChatHub, IChatClient> hubContext)
{_hubContext = hubContext;
}public async Task<JsonResult> OnPostAsync(string user)
{if (string.IsNullOrWhiteSpace(user)){return new JsonResult(new { status = "fail", message = "NoUser" });}await Task.Factory.StartNew(async () =>{var rnd = new Random(DateTime.Now.Millisecond);for (var i = 0; i < 10; i++){await _hubContext.Clients.Client(user).EchartsMessage(new[] {$"{rnd.Next(100,300)}",$"{rnd.Next(100,320)}" ,$"{rnd.Next(100,310)}","",$"{rnd.Next(10,30)}",$"{rnd.Next(10,30)}","",$"{rnd.Next(130,310)}",$"{rnd.Next(130,310)}",$"{rnd.Next(13,31)}",$"{rnd.Next(13,31)}","",$"{rnd.Next(130,310)}",$"{rnd.Next(130,310)}",$"{rnd.Next(13,31)}",$"{rnd.Next(130,310)}",$"{rnd.Next(130,310)}"});await Task.Delay(2000);}}, TaskCreationOptions.LongRunning);return new JsonResult(new { status = "ok" });
}

随后我们访问以下这个页面,就可以看到目前这种效果

下面我们来编写前端js,用来和后端服务通过SignalR通信,在wwwroot/js下新建一个echartchat.js

"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").withAutomaticReconnect().configureLogging(signalR.LogLevel.Debug).build();
var user = "";
var chartDom = document.getElementById('main');
var myChart = window.echarts.init(chartDom);connection.on("GetMyId", function (data) {user = data.userId;//SignalR返回的数据字段开头是小写console.log(user);
});
connection.on("ReceiveMessage", function (data) {console.log(data.userId + data.context);
});connection.on("EchartsMessage", function (data) {console.log(data);var option = {series: [{data: data}]};myChart.setOption(option);//更新Echarts数据
});connection.start().then(function () {console.log("服务器已连接");
}).catch(function (err) {return console.error(err.toString());
});

保存后我们再次访问页面,并点击按钮,就可以实现后台推送数据给前台echarts来展示图标的效果。

搜索

复制

ASP.NET Core 使用SignalR后台实时推送数据给Echarts展示图表相关推荐

  1. 【收藏】spring boot+websocket+echarts 后台推送数据用echarts展示

    https://gitee.com/heibaifu/websocket.git 下载工程到本地,运行WebsocketApplication,浏览器访问http://localhost:8080/i ...

  2. websocket实现GPS数据的实时推送与地图的展示(优化)

    概述 前两天,发布了一片文章websocket实现GPS数据的实时推送与地图的展示,文章发出后引来了不少读者的关注,也有不少读者要求做进步一优化.本文应大家的要求,对上文的内容做一个优化,优化地方包括 ...

  3. asp.net core使用serilog将日志推送到腾讯云日志服务

    为什么是serilog? Serilog是 .NET 中最著名的结构化日志类库. 基于日志事件log events,而不是日志消息log message. 你可以将日志事件格式化为控制台的可读文本或者 ...

  4. winform调用websocket_C#基于websocket的前台及后台实时推送

    实现步骤如下: 1.获取GoEasy appkey. 在goeasy官网上注册一个账号,并新建一个app. APP创建好后系统会为该app自动生成两个key, 一个既可以用来接收又可以用来推送 (su ...

  5. SignalR网页实时推送

    1.新建项目,选择mvc4 Wed应用程序,选择Internet,视图引擎:Razor 2.在控制器中添加 并添加上视图 3.引用(install-package Microsoft.AspNet.S ...

  6. ASP.NET Web实时消息后台服务器推送技术---GoEasy

    越来越多的项目需要用到实时消息的推送与接收,怎样用ASP.NET实现最方便呢?我这里推荐大家使用GoEasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送! 浏览器兼容性:GoEa ...

  7. Python Web实时消息后台服务器推送技术---GoEasy

    越来越多的项目需要用到实时消息的推送与接收,怎样实现最方便呢?我这里推荐大家使用GoEasy,它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送! 浏览器兼容性:GoEasy推送 支持we ...

  8. C# Web实时消息后台服务器推送技术---GoEasy

    越来越多的项目需要用到实时消息的推送与接收,怎样实现最方便呢?我这里推荐大家使用GoEasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送! 浏览器兼容性:GoEasy推送 支持w ...

  9. C# Web实时消息后台服务器推送技术-GoEasy

    越来越多的项目需要用到实时消息的推送与接收,怎样用C#实现最方便呢?我这里推荐大家使用GoEasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送! 浏览器兼容性:GoEasy推送 ...

最新文章

  1. unzip 压缩包含路径,解压缩覆盖路径下的同名文件
  2. Matlab自定义函数的几种方法
  3. 学python用ubuntu还是win10_Windows 10上使用Ubuntu的优点
  4. sql语句中查询出的数据添加一列,并且添加默认值
  5. java 分层领域模型_Java领域模型 | 学步园
  6. tp快捷路径 __URL__和__APP__
  7. PostgreSQL11.7逻辑复制的搭建
  8. 在centos 7上自动安装starUML,且破解之。
  9. unity打包IOS填坑1
  10. OC语法8——@class关键字
  11. 海思Hi3519AV100sensor移植之二-- imx586 sensor
  12. Tomcat 弱密码爆破 漏洞复现
  13. 【信息系统项目管理师】2018下半年系统集成项目管理工程师案例分析
  14. 德尔菲法 Delphi 专家判断
  15. 理性的赌徒-SSD写带宽保持恒稳的秘密
  16. 农村房屋房产证怎么申请
  17. intern string java_聊聊java String的intern
  18. 搜索引擎的小技巧【可以组合起来使用】:
  19. 2003server计算机管理里面没有本地用户和组
  20. 数字化为宝马带来了什么

热门文章

  1. acl 影响因子_计算机领域EI和SCI收录期刊、影响因子及国际会议
  2. 软件压力测试有哪些测试流程?软件测试报告收费情况
  3. 不敲代码用ChatGPT开发一个App
  4. 中小企业网络构架环境搭建
  5. STM32Cube中usart的使用
  6. 以马丁格尔(翻倍加仓)为基础的长线交易策略
  7. 基于KNN的分类模型-预测美团外卖城市等级
  8. 关于JDK8和JDK11切换问题
  9. Pikachu靶场通过记录
  10. 公司项目vue cli2升级到vue cli3