ASP. NET Signal是为ASP.NET开发人员提供的一个库,可以简化开发人员将实时Web功能添加到应用程序的过程。实时Web功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。
我个人的理解是:当客户端向服务器端发起一次请求,建立连接之后,当服务器端数据发生了变化,无需客户端再次发起请求,服务器端即可将更新后的数据主动推送给客户端。实际工作中可以用它做很多事情,如果用户是通过刷新web页面,来查看新的数据,或者是通过页面实现长轮询来检索新的数据,那么就该考虑使Signal了。示例包括仪表板和监视应用程序、协作应用程序(例如同时编辑文档)、工作进度更新和实时表单等等。
Signal会自动管理连接,并允许您像Chat室那样向所有连接的客户端同时发送消息。你也可以向特定的客户端发送消息。客户端和服务器之间的连接是持久性的,不像传统的HITP连接每个通信都需要重新建立一个连接Signal支持“服务器推送”功能,即服务器代码可以使用远程过程调用(PRC)来调用浏览器中的客户端代码,而不使用目前在Web上常用的请求ー响应模型Signal应用程序可以通过使用服务总线。SQL Server或 Redis扩展到数以千计的客户端Signal是开源的,可以通过 Github访问。
由于VFS系统功能逻辑较为复杂,某些功能操作后等待时间较长,可以运用SignalR来减少使用者在等待返回结果上的时间浪费。例如:对账单刷新功能,此功能需要刷新报表中的相关结算单位的当月的对账单明细、对账单汇总的数据,由于报表的逻辑较为复杂,因此如果结算单位单量很大的情况下刷新的过程比较长,因此引入SignalR,当客户端运行时会首先与服务器建立连接,发起对账单刷新请求时,会异步执行数据的刷新操作,异步执行的过程中会直接返回“系统正在刷新数据”的通知消息,此时,使用者不必在此等候,可先去做其他工作,等数据刷新执行完毕后,服务器会主动向客户端发起消息通知,通知客户端对账单刷新已完成。
Demo下载地址(可点击此处下载)
服务器端:
Microsoft.AspNet.SignalR/Microsoft.AspNet.SignalR.Core/Microsoft.AspNet.SignalR.JS等
(3)在Startup.cs项目启动文件中加入SignalR的启动配置
app.Map("/signalrapi", map =>
{
// 跨域支持
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
};
map.RunSignalR(hubConfiguration);
});
注:需要引入包using Microsoft.AspNet.SignalR; 和 using Microsoft.Owin.Cors;
(4)在新建的SingnalR项目中新建文件夹MsgHubs,并在此文件夹下新建类MsgHub,此类需集成Hub类(Microsoft.AspNet.SignalR.Hub)。此类用于写客户端与服务器端交互的公用方法,例如:客户端启动或刷新时调用服务器端记录当前登陆人信息
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SignalR.MsgHubs
{
public class MsgHub : Hub
{
public static dynamic client { get; set; }
public static Dictionary<string, string> _clients = new Dictionary<string, string>();
/// <summary>
/// 客户端调用服务器,记录用户唯一标识
/// </summary>
/// <param name="message"></param>
public void ClientToServer(string message)
{
if (!_clients.ContainsKey(message))
{
_clients.Add(message, Context.ConnectionId);
}
else
{
_clients.Remove(message);
_clients.Add(message, Context.ConnectionId);
}
}
}
}
(5)新建的项目中都会默认有一个Class类,可将其重命名用于写向指定用户发送请求的公用方法
using Lunz.Services;
using Microsoft.AspNet.SignalR;
using SignalR.MsgHubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SignalR
{
public class MsgHelper
{
private static IHubContext _chat;
public static IHubContext Chat
{
get
{
if (_chat == null)
{
_chat = GlobalHost.ConnectionManager.GetHubContext<MsgHub>();
}
return _chat;
}
}
private static MsgHelper _current;
public static MsgHelper Current
{
get
{
if (_current == null)
{
_current = new MsgHelper();
}
return MsgHelper._current;
}
}
/// <summary>
/// 向指定用户发送消息
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public WebApiResult Send(string userName, MessageInfo msgInfo)
{
var result = new WebApiResult();
try
{
//此处需引入MsgHub类
if (MsgHub._clients.ContainsKey(userName))
{
var connectId = MsgHub._clients[userName];
//发送到指定客户端
//让客户端获取最新的消息
Chat.Clients.Client(connectId).getNewMessage(msgInfo);
//Chat.Clients.Client(connectId).serverToClient(msgInfo+" "+DateTime.Now.ToString("yyyy-MM-dd"));
//发送到所有客户端
//Clients.All.serverToClient(message + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
}
catch
{
}
return result;
}
}
}
public class MessageInfo
{
public int Id { get; set; }
public string Message { get; set; }
public Nullable<System.DateTime> SendAt { get; set; }
public Nullable<System.Guid> ReceiveUserId { get; set; }
public string ReceiveUserName { get; set; }
public string ReceiveUserCode { get; set; }
public bool IsRead { get; set; }
public Nullable<System.DateTime> ReadTime { get; set; }
public Nullable<System.DateTime> InsertTime { get; set; }
public bool Deleted { get; set; }
}
(6)新建Ctroller&Service专门用于消息的记录与发送
/// <summary>
/// 对账单刷新
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[ActionName("BillInfoRefresh")]
[HttpPost]
public WebApiResult BillInfoRefresh (CustConfirmDetailModel model)
{
var result = new WebApiResult();
//异步执行,执行完毕后会将执行结果反馈到客户端
_messageService.BillInfoRefreshTast(model);
return result;
}
注:异步方法无法获取HttpContext.Current,此值为空,在获取CurrentUser信息时会报错,因此,此处可将异步方法写在方法体内
public void BillInfoRefreshTast(CustConfirmDetailModel model)
{
var result = new WebApiResult();
MessageModel message = new MessageModel();
List<sys_message> messageList = new List<sys_message>();
var curUserId = CurrentUser?.UserId;
var curUserName = CurrentUser?.Username;
var curUserCode = CurrentUser?.DisplayName;
Task.Run(() =>
{
var check = _exportService.UserPermissionInfoById(model);
if (!check.Success)
{
result.AddError(check.AllMessages);
sys_message msgInfo = new sys_message() {
Message = $"对账单刷新失败!错误信息:{result.AllMessages}",
SendAt = DateTime.Now,
ReceiveUserId = curUserId,
ReceiveUserName = curUserName,
ReceiveUserCode = curUserCode,
IsRead = false,
InsertTime = DateTime.Now
};
messageList.Add(msgInfo);
MsgHelper.Current.Send(curUserName, Mapper.Map<MessageInfo>(msgInfo));
}
// 对账单汇总
var res = _reportService.InsertCustConfirmInfo(model);
if (res.Success)
{
// 最账单明细汇总
var res_mx = _reportService.InsertCustConfirmDetail(model);
sys_message msgInfo = new sys_message()
{
Message = "对账单刷新成功!",
SendAt = DateTime.Now,
ReceiveUserId = curUserId,
ReceiveUserName = curUserName,
ReceiveUserCode = curUserCode,
IsRead = false,
InsertTime = DateTime.Now
};
messageList.Add(msgInfo);
//发送对账单汇总成功消息
MsgHelper.Current.Send(curUserName, Mapper.Map<MessageInfo>(msgInfo));
}
else
{
sys_message msgInfo = new sys_message()
{
Message = $"对账单刷新失败!错误信息{res.AllMessages}",
SendAt = DateTime.Now,
ReceiveUserId = curUserId,
ReceiveUserName = curUserName,
ReceiveUserCode = curUserCode,
IsRead = false,
InsertTime = DateTime.Now
};
messageList.Add(msgInfo);
MsgHelper.Current.Send(curUserName, Mapper.Map<MessageInfo>(msgInfo));
}
message.MessageList = messageList;
this.InsertSysMessage(message);
});
}
客户端:
1、安装nuget包:Microsoft.AspNet.SignalR.JS
<script src="~/Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="@System.Configuration.ConfigurationManager.AppSettings["ApiBaseUrl"]/signalrapi/hubs"></script>
<!-- 消息提示控件的js -->
<script src="~/Content/js/message/message.common.js"></script>
<script src="~/Content/js/message/message.directives.js"></script>
<script type="text/javascript">
/*初始化SignalR*/
//$(function () {
// // 申明一个Hub代理引用,首字母小写
// var hub = $.connection.msgHub;
// // 服务端调用客户端
// hub.client.serverToClient = function (message) {
// console.log("message:", message);
// }
// // signalr/hubs桥接
// $.connection.hub.url = apiBaseUrl + "signalrapi";
// // 启用Hub事件的日志记录
// $.connection.hub.logging = true;
// // 启动Hub连接,指定传输协议
// $.connection.hub.start({ transport: ['webSockets', 'longPolling'] }).done(function () {
// hub.server.clientToServer("zhaoqian");
// });
//});
/* Init Metronic's core jquery plugins and layout scripts */
$(document).ready(function () {
Metronic.init(); // Run metronic theme
Metronic.setAssetsPath('/content/assets/'); // Set the assets folder path
});
</script>
注:近期有很多朋友想要加qq跟我探讨交流,因此我建立了一个技术交流沟通群,另外群内也会分享一些好的技术资源,大家感兴趣的可以进群,此项目的源码在群文件中也可找到(群号码:1055109975,可扫描下方二维码进群)









2、配置相关js

1314

被折叠的 条评论
为什么被折叠?



