什么是 SignalR ASP.NET Core
javascript
ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能。 实时 web 功能使服务器端代码能够当即将内容推送到客户端。html
SignalR ASP.NET Core能够作什么前端
• 须要从服务器进行高频率更新的应用。 示例包括游戏、社交网络、投票、拍卖、地图和 GPS 应用。
• 仪表板和监视应用。 示例包括公司仪表板、即时销售更新或旅行警报。
• 协做应用。 协做应用的示例包括白板应用和团队会议软件。
• 须要通知的应用。 社交网络、电子邮件、聊天、游戏、旅行警报和不少其余应用都需使用通知。java
SignalR ASP.NET Core特点jquery
• 自动处理链接管理。
• 可将消息同时发送到全部链接的客户端。
• 可向特定客户端或客户端组发送消息。
• 可缩放以处理不断增长的流量。
• SignalR采用rpc来进行客户端与服务器端之间的通讯。
• SignalR会自动选择服务器和客户端的最佳传输方法(WebSockets、Server-Sent事件、长轮询)SignalR能够根据当前浏览器所支持的协议来选择最优的链接方式,从而可让咱们把更多的精力放在业务上而不是底层传输技术上。web
哪些浏览器支持SignalR ASP.NET Coreajax
Apple Safari(包含IOS端)、Google Chrome(包括 Android端)、Microsoft Edge、Mozilla Firefox等主流浏览器都支持SignalR ASP.NET Core。json
本次咱们将实现一个经过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中,咱们主要是定义统一的服务端调用客户端方法的统一方法名(防止每次都要手动输入调用方法是出现失误而致使调用失败的低级错误)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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中,咱们主要定义的是序列化后的交互用的实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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接口,从而就能够在方法中直接调用接口名称来和客户端交互。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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错误
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
void
ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddRazorPages()
#if DEBUG
//Debug下禁用XSRF防御,方便调试
.AddRazorPagesOptions(o =>
{
o.Conventions.ConfigureFilter(
new
IgnoreAntiforgeryTokenAttribute());
})
#endif
;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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文件,同时编写一个请求后台接口的方法,调用这个方法后,后台就会主动推送屡次数据给前台。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
<!
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来实现和服务器端数据实时交互。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
@page
@model signalr.Pages.echarts.IndexModel
@{
ViewBag.Title = "Echarts图标展现";
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来建立一个任务执行这个操做。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
"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来展现图标的效果。
什么是 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中,咱们主要是定义统一的服务端调用客户端方法的统一方法名(防止每次都要手动输入调用方法是出现失误而致使调用失败的低级错误)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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中,咱们主要定义的是序列化后的交互用的实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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接口,从而就能够在方法中直接调用接口名称来和客户端交互。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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错误
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
void
ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddRazorPages()
#if DEBUG
//Debug下禁用XSRF防御,方便调试
.AddRazorPagesOptions(o =>
{
o.Conventions.ConfigureFilter(
new
IgnoreAntiforgeryTokenAttribute());
})
#endif
;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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文件,同时编写一个请求后台接口的方法,调用这个方法后,后台就会主动推送屡次数据给前台。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
<!
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来实现和服务器端数据实时交互。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
@page
@model signalr.Pages.echarts.IndexModel
@{
ViewBag.Title = "Echarts图标展现;
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来建立一个任务执行这个操做。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
"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来展现图标的效果。