在 Asp.NET MVC 中使用 SignalR 实现推送功能

  一,简介

  Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架。它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息。

  二,实现机制

  SignalR 的实现机制与 .NET WCF 或 Remoting 是相似的,都是使用远程代理来实现。在具体使用上,有两种不同目的的接口:PersistentConnection 和 Hubs,其中 PersistentConnection 是实现了长时间的 Javascript 轮询(类似于 Comet),Hub 是用来解决实时信息交换问题,它是利用 Javascript 动态载入执行方法实现的。SignalR 将整个连接,信息交换过程封装得非常漂亮,客户端与服务器端全部使用 JSON 来交换数据。

  下面就 Hubs 接口的使用来讲讲整个流程:

  1,在服务器端定义对应的 hub class;

  2,在客户端定义 hub class 所对应的 proxy 类;

  3,在客户端与服务器端建立连接(connection);

  4,然后客户端就可以调用 proxy 对象的方法来调用服务器端的方法,也就是发送 request 给服务器端;

  5,服务器端接收到 request 之后,可以针对某个/组客户端或所有客户端(广播)发送消息。

  三,Hub 示例教程

  1,工具准备

  SignalR 运行在 .NET 4.5 平台上,所以需要安装 .NET 4.5。为了方便演示,本示例使用 ASP.NET MVC 在 Win 7 系统来实现。这需要安装 ASP.NET MVC 3 或 ASP.NET MVC 4。

  2,建立工程

  打开 VS2010/VS2012 新建名为 SignalRTutorial 的 ASP.NET MVC 3 Web Application 工程,选择 Internet Application 模板, Razor 视图引擎以及勾选 Use HTMl 5 标签。

  

  3,安装 SignalR

  打开 NuGet 的 package manager console(Tools->Library package manager),输入:install-package SignalR.Sample,回车安装。如图所示:

  

  4,实现 Hub 服务器端代码

  向工程中新建 SignalR 目录,在其中添加 ChatHub.cs 文件,内容如下:

  namespace SignalTutorial.SignalR

  {

  [HubName("chat")]

  public class Chat : Hub

  {

  public void Send(string clientName, string message)

  {

  //var toSelfinfo = "You had sent message " + message;

  //Caller.addSomeMessage(clientName, toSelfinfo);

  // Call the addMessage method on all clients

  Clients.addSomeMessage(clientName, message);

  //Clients[Context.ConnectionId].addSomeMessage(clientName, data);

  }

  }

  }

  在上面的代码中:

  1),HubName 这个特性是为了让客户端知道如何建立与服务器端对应服务的代理对象,如果没有设定该属性,则以服务器端的服务类名字作为 HubName 的缺省值;

  2),Chat 继承自 Hub,从下面 Hub 的接口图可以看出:Hub 支持向发起请求者(Caller),所有客户端(Clients),特定组(Group) 推送消息。

  3),public void Send(string clientName, string message) 这个接口是被客户端通过代理对象调用的;

  4),Clients 是 Hub 的属性,表示所有链接的客户端页面,它和 Caller 一样是 dynamic,因为要直接对应到 Javascript 对象;

  5),Clients.addSomeMessage(clientName, message); 表示服务器端调用客户端的 addSomeMessage 方法,这是一个 Javascript 方法,从而给客户端推送消息。

  

  6),总结:这里实现的服务很简单,就是当一个客户端调用 Send 方法向服务器发送 message 后,服务器端负责将该 message 广播给所有的客户端(也可以给特定组或特定客户端,见屏蔽代码),以实现聊天室的功能。

  5,实现 Hub 客户端代码

  1),引用 SignalR Javascript

  为了简化引用 SignalR 脚本操作,我直接在 View/Shared/_Layout.cshtml 中引入 SignalR 及其他脚本:

  

  

  

  

  

  

  

  

  

  

  

  注意:signalR 依赖于 jquery,所以 signalR 必须放在 jquery 之后,而 hubs 又必须放在 signalR 之后。

  然后在 body 部分加入 HubChat Tab:

  

  • @Html.ActionLink("HubChat", "HubChat", "Home")

      2),生成访问页面

      在 HomeController 中添加如下方法:

      public ActionResult HubChat()

      {

      ViewBag.ClientName = "用户-" + Rnd.Next(10000, 99999);

      return View();

      }

      这里由服务器根据随机数来设定客户端的名字,不够严谨,因为随机数生成的名字不是唯一的的,在这里仅为简化演示,实际应用中应该使用 GUID 。

      然后生成对应的 View:HubChat.cshtml

      @model dynamic

      @{

      ViewBag.Title = "title";

      }

      

      

      

    Hub Chat

      

      

      

      

      

      

      

      消息记录: (你是:@ViewBag.ClientName):

      

      

        

      

      在上面的页面代码中,我添加了名为 hubDemo.js 的脚本,这将在下面介绍;此外还有一个id 为 Placeholder 的隐藏 input 控件,这是为了向 Javascript 中传递客户端的名字。

      3),编写 Javascript

      向 Scripts 目录添加新的 Javescript 脚本:hubDemo.js。其内容如下:

      $(function () {

      var myClientName = $(‘#Placeholder‘).val();

      // Proxy created on the fly

      var chat = $.connection.chat;

      // Declare a function on the chat hub so the server can invoke it

      chat.addSomeMessage = function (clientName, message) {

      writeEvent(‘‘ + clientName + ‘ 对大家说: ‘ + message, ‘event-message‘);

      };

      $("#broadcast").click(function () {

      // Call the chat method on the server

      chat.send(myClientName, $(‘#msg‘).val())

      .done(function () {

      console.log(‘Sent message success!‘);

      })

      .fail(function (e) {

      console.warn(e);

      });

      });

      // Start the connection

      $.connection.hub.start();

      //A function to write events to the page

      function writeEvent(eventLog, logClass) {

      var now = new Date();

      var nowStr = now.getHours() + ‘:‘ + now.getMinutes() + ‘:‘ + now.getSeconds();

      $(‘#messages‘).prepend(‘

  • ‘ + nowStr + ‘ ‘ + eventLog + ‘.‘);

      }

      });

      上面代码有详细的注释,下面再讲讲关键之处:

      1,首先获取客户端页面的名字;

      2,然后通过 $.connection.chat 建立对应服务器端 Hub 类的代理对象 chat;

      3,定义客户端的 Javascript 方法 addSomeMessage ,服务器通过 dynamic 方式调用客户端的该方法以实现推送功能。在这里每当收到服务器推送来的消息,就在客户端页面的 messages 列表表头插入该消息。

      4,当点击广播按钮时,客户端通过代理对象调用服务器端的 send 方法以实现向服务器发送消息。

      5,通过 $.connection.hub.start(); 语句打开链接。

      6),编译运行 Hub 示例

      在多个浏览器窗口打开页面,效果如下:

      

      

      四,Persistent Connection 示例教程

      1,实现服务器端代码

      1),编写服务器 PersistentConnection 代码

      向工程中 SignalR 目录中添加 PersistentConnection.cs 文件,内容如下:

      using System;

      using System.Collections.Generic;

      using System.Threading.Tasks;

      using SignalR;

      namespace SignalTutorial.SignalR

      {

      public class MyConnection : PersistentConnection

      {

      protected override Task OnConnectedAsync(IRequest request, string connectionId)

      {

      return Connection.Broadcast("Connection " + connectionId + " connected");

      }

      protected override Task OnReconnectedAsync(IRequest request, IEnumerable groups, string clientId)

      {

      return Connection.Broadcast("Client " + clientId + " re-connected");

      }

      protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)

      {

      var info = data + ". ConnectionId is [" + connectionId + "]";

      // return Connection.Send(connectionId, info);

      // Broadcast data to all clients

      return Connection.Broadcast(info);

      }

      protected override Task OnDisconnectAsync(string connectionId)

      {

      return Connection.Broadcast("Connection " + connectionId + " disconncted");

      }

      protected override Task OnErrorAsync(Exception error)

      {

      return Connection.Broadcast("Error ocurred " + error);

      }

      }

      }

      在上面的代码中:

      1,MyConnection 继承自 PersistentConnection,这样我们就能在客户端连接,重连接,断开连接,发送消息以及连接出错的情况下进行相关的处理。从下面的 PersistentConnection 接口中可以看到,PersistentConnection 同样支持组进行推送。

      

      2,推送消息由 PersistentConnection 的属性 Connection 来提供,它继承自 IConnection 接口,该接口提供两个函数来实现对特定客户端的推送和广播功能。

      System.Threading.Tasks.Task Send(string signal, object value)

      System.Threading.Tasks.Task Broadcast(object value)

      2),配置访问路由

      为了支持客户端访问,需要在路由表中进行配置。打开 Global.asax.cs ,修改 Application_Start() 函数如下:

      protected void Application_Start()

      {

      AreaRegistration.RegisterAllAreas();

      RouteTable.Routes.MapConnection("echo", "echo/{*operation}");

      RegisterGlobalFilters(GlobalFilters.Filters);

      RegisterRoutes(RouteTable.Routes);

      // Make connections wait 50s maximum for any response. After

      // 50s are up, trigger a timeout command and make the client reconnect.

      GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(50);

      //DisconnectTimeout

      //HeartBeatInterval

      //KeepAlive

      }

      在上面的代码中,我将 echo 及其子路径的访问映射到 MyConnection 上,并设置连接超时时间为 50 s。在这里还可以设置其他的一些参数,如断连超时时间,心跳间隔等。

      2,实现客户端代码

      1),生成访问页面

      在前面三 Hub 示例教程的基础上,我们向该工程加入使用 Persistent Connection 的演示。和前面一样,向 _Layout.cshtml 中加入 PersistentChat Tab:

      

  • @Html.ActionLink("PersistentChat", "PersistentChat", "Home")

      然后在 HomeController 中添加如下方法:

      public ActionResult PersistentChat()

      {

      ViewBag.ClientName = "用户-" + Rnd.Next(10000, 99999);

      return View();

      }

      这里由服务器根据随机数来设定客户端的名字,不够严谨,因为随机数生成的名字不是唯一的的,在这里仅为简化演示,实际应用中应该使用 GUID 。

      然后生成对应的 页面: PersistentChat.cshtml:

      @model dynamic

      @{

      ViewBag.Title = "title";

      }

      

      

    Persistent Chat

      

      

      

      

      

      

      

      消息记录: (你是:@ViewBag.ClientName):

      

      

        

      

      在上面的页面代码中,我添加了名为 persistent.js 的脚本,这将在下面介绍;此外还有一个id 为 Placeholder 的隐藏 input 控件,这是为了向 Javascript 中传递客户端的名字。

      2),编写 Javascript

      向 Scripts 目录添加新的 Javescript 脚本:persistent.js。其内容如下:

      $(function () {

      var myClientName = $(‘#Placeholder‘).val();

      var connection = $.connection(‘/echo‘);

      connection.received(function (data) {

      var msg = new String(data);

      var index = msg.indexOf("#");

      var clientName = msg.substring(0, index);

      var content = msg.substring(index + 1);

      if (clientName == null || clientName == "") {

      writeEvent(‘‘ + "系统消息" + ‘: ‘ + content, ‘event-message‘);

      }

      else {

      writeEvent(‘‘ + clientName + ‘ 对大家说: ‘ + content, ‘event-message‘);

      }

      });

      connection.start();

      $("#broadcast").click(function () {

      var msg = myClientName + "#" + $(‘#msg‘).val();

      connection.send(msg);

      });

      //A function to write events to the page

      function writeEvent(eventLog, logClass) {

      var now = new Date();

      var nowStr = now.getHours() + ‘:‘ + now.getMinutes() + ‘:‘ + now.getSeconds();

      $(‘#messages‘).prepend(‘

  • ‘ + nowStr + ‘ ‘ + eventLog + ‘.‘);

      }

      });

      上面的代码基本与前面的 Hub 实现相同,在此就不再一一讲述。有两点值得说明:

      1,创建连接时,指定路径为 "/echo",该路径在服务器端的路由映射表被映射为 MyConnection,因而这个连接就被指向前面提供的 MyConnection。

      2,将 clientName 信息放入 message 中,并用 # 将 clientName 和消息内容连接成一个 msg。

      3,编译运行 Persistent 示例

      

      

  • 时间: 2024-07-28 17:55:56

    在 Asp.NET MVC 中使用 SignalR 实现推送功能的相关文章

    在 Asp.NET MVC 中使用 SignalR 实现推送功能 [转]

    在 Asp.NET MVC 中使用 SignalR 实现推送功能 罗朝辉 ( http://blog.csdn.net/kesalin ) CC许可,转载请注明出处 一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息. 可访问其官方网站:https://github.com/SignalR/ 获取更多资讯. 二,实现机制

    Asp.NET MVC 中使用 SignalR 实现推送功能

    一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息. 可访问其官方网站:https://github.com/SignalR/ 获取更多资讯. 二.Asp.net SignalR 是个什么东东 Asp.net SignalR是微软为实现实时通信的一个类库.一般情况下,SignalR会使用JavaScript的长轮询(lo

    Asp.NET MVC 使用 SignalR 实现推送功能二(Hubs 在线聊天室 获取保存用户信息)

    简单介绍 关于SignalR的简单实用 请参考 Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室) 在上一篇中,我们只是介绍了简单的消息推送,今天我们来修改一下,实现保存消息,历史消息和用户在线 由于,我这是在一个项目([无私分享:从入门到精通ASP.NET MVC]从0开始,一起搭框架.做项目 目录索引)的基础上做的,所以使用到的一些借口和数据表,不详细解析,只是介绍一下思路和实现方式,供大家参考 用户登录注册信息 当用户登录之后,我们注册一下用户的信息,我们

    在Asp.Net MVC中实现SignalR的广播与定向推送

    首先说明一下这个文章是自己在使用SignalR的时候做个记录,目的是怕以后忘记了,因为我也不常用,做这样一个简单的demo以后用到的时候可以翻翻看. 至于SignalR是个什么玩意呢请您去自行百度一下,这里不过多赘述. 下面直入主题! 场景: 我们有个网站,在登录界面有个二维码登录功能,用户打开我们的APP点击扫码登录扫描网页上的二维码,这个时候我想要在页面上(网站登录页)做点反应,当用户在APP端扫描完毕之后,网站登录页上提示  --用户扫描已完成,请在手机上确认-- 等字样. 为了实现这个功

    Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs)

    简介 ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消息及调用方法,当然这是实时操作的. WebSockets是HTML5提供的新的API,可以在Web网页与服务器端间建立Socket连接,当WebSockets可用时(即浏览器支持Html5)SignalR使用WebSockets,当不支持时SignalR将使用其它技术来保证达到相同效果. Sign

    ASP.NET 微信公众平台模板消息推送功能完整开发

    最近公众平台的用户提出了新需求,他们希望当收到新的邮件或者日程的时候,公众平台能主动推送一条提醒给用户.看了看平台提供的接口,似乎只有[模板消息]能尽量满足这一需求,但不得不说微信提供的实例太少,而且只有PHP的,不过摸索了一下还是成功的实现了. 首先是准备工作,需要申请开通[模板消息]功能,网上教程很多.然后申请通过之后,用户可以从现有的模板里选择15个使用,也可以自己添加模板使用.这里吐槽一下:申请添加新的模板时,微信出于保护用户的目的禁止了一些“看起来会很频繁”的消息类型,比如这图里的——

    在ASP.NET MVC中使用NuGet添加SignalR类库之后,再次运行程序时,它出现了一个异常:

    自从在ASP.NET MVC中使用NuGet添加SignalR类库之后,再次运行程序时,它出现了一个异常: Server Error in '/' Application. The following errors occurred while attempting to load the app.- No assembly found containing an OwinStartupAttribute.- No assembly found containing a Startup or [

    《ASP.NET SignalR系列》第五课 在MVC中使用SignalR

    接着上一篇:<ASP.NET SignalR系列>第四课 SignalR自托管(不用IIS) 一.概述 本教程主要阐释了如何在MVC下使用ASP.NET SignalR. 添加SignalR库到MVC中. 创建hub和OWIN startup 类来推送内容到客户端. 在页面中使用SignalR jQuery 库发送消息和呈现从来得更新. 下面屏幕截图展示了一个完成的聊天应用程序 二.创建项目 1.用MVC5 .NET4.5 创建一个名为SignalRChat的项目 2.改变授权. 3.选择 N

    MVC中使用SignalR

    MVC中使用SignalR打造酷炫实用的即时通讯功能附源码 前言,现在这世道写篇帖子没个前言真不好意思发出来.本贴的主要内容来自于本人在之前项目中所开发的一个小功能,用于OA中的即时通讯.由于当时走的太急,忘记把代码拿出来.想想这已经是大半年前的事情了,时间过了这么久,在当时最新的SignalR2.0.1到现在已经变成了2.2.昨天晚上特地熬了个夜,重新又把它写出来做了一个小小的Demo.当然我只是大自然的搬运工,这个SignalR即时通讯功能里面有一些前端的类库不是我自己写的.我只是改吧改吧~