主动推送消息有两种方案:
1.使用C#的signalr主动推送消息
2.使用ajax轮询,本质上还是前端向后端请求
这里采用signalr
来实现主动的消息推送(无前端调用),同时结合前一篇博客的定时功能(.net mvc——定时任务实现),实现了服务端定时向前端推送消息,前端更新页面显示的功能。
实现的效果如下:这里我是利用Timer进行定时,服务器后端每间隔一秒就向网页前端推送一次信息。
主要实现步骤及代码
1. 集线器Hub类(放在了新建的Hubs文件夹下,注意这里SendMsg方法与之前不同)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using TimerMvcWeb.Filters;
namespace TimerMvcWeb.Hubs
{
[HubName("msgHub")]//客户端调用,首字母要小写
public class MsgHub : Hub
{
public static int count = 0;
[HubMethodName("sendMsg")]//客户端调用,首字母要小写
public void SendMsg()
{
//因为在后台调用,所以要这样写,否则会出错,提示Using a Hub instance not created by the HubPipeline is unsupported
var hubContext = GlobalHost.ConnectionManager.GetHubContext<MsgHub>();
hubContext.Clients.All.getMsg("调用次数:" + count); //用户调用客户端的函数
count++;
//Clients.All.getMsg("调用次数:"+count);
}
}
}
2.Startup类(也放在Hubs文件夹下)
using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
[assembly: OwinStartup(typeof(TimerMvcWeb.Hubs.Startup))]
namespace TimerMvcWeb.Hubs
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Any connection or hub wire up and configuration should go here
app.MapSignalR();
}
}
}
3.前端html代码
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>TimerMsgShow</title>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.1.2.js"></script>
<script src="/signalr/hubs"></script>
<script>
$(function () {
serverClient();
});
//服务器连接操作
function serverClient() {
//注册服务器连接
var msgHub = $.connection.msgHub;
//2.给客户端注册方法,被服务器调用的方法,
//服务器主动调用,给txt内容,客户端被动接收
//接收到之后做什么
msgHub.client.getMsg = function (txt) {
var txtHtml = '<li><strong>' + htmlEncode(txt) + '</li>';
$("#msgList").append(txtHtml);
//alert(txt);
}
//3.启动连接并绑定处理事件
$.connection.hub.start().done(function () {
$("#sendBtn").removeAttr("disabled");
console.info("start!");
//$("#sendBtn").click(function () {
// msgHub.server.sendMsg(sessionStorage.getItem("user"), $("#txtMsg").val());
// //$('#txtMsg').val('').focus();
//})
}).fail(function () {
});
}
// 将发来的信息转化为html标签以便添加到页面
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
</head>
<body>
<div id="msgList">
</div>
@*<input type="text" id="txtName" name="name" value="" />
<button id="btnLogin">登录</button>*@
<input type="text" id="txtMsg" name="name" value="" />
<button id="sendBtn" disabled="disabled">发送消息</button>
</body>
</html>
4.定时任务调用集线器hub类的方法,需要先实现定时功能(参考)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using TimerMvcWeb.Filters;
using TimerMvcWeb.Hubs;
namespace TimerMvcWeb.AutoTask
{
/// <summary>
/// 测试任务,从程序启动开始,每1秒执行一次
/// </summary>
[AutoTask(EnterMethod = "StartTask", IntervalSeconds = 1, StartTime = "")]
public class TestTask
{
public static void StartTask()
{
//调用集线器方法,向前台发送消息
MsgHub hub = new MsgHub();
hub.SendMsg();
}
}
}
如果不用定时只推送一次消息,也可以在Global.asax的Application_Start() 函数创建线程类的事例。这样网站启动时线程就启动了。
但这里有一个小问题:
当我的服务器只向前端推送一次消息时,我打开相应的网页往往收不到消息的推送,调试后发现主动推送的代码确实是执行了。
原因:
原因应该是网页的加载没有主动推送代码执行的快,当服务器调用客户端方法时,网页还未加载完成,所以推送的消息在网页上还显示不出来。
解决办法:
将定时推送的时间间隔加大为两秒后推送消息时,网页就能正常收到推送的消息。