一步一步学习SignalR进行实时通信_5_Hub

原文:一步一步学习SignalR进行实时通信_5_Hub

一步一步学习SignalR进行实时通信\_5_Hub

SignalR


  • 一步一步学习SignalR进行实时通信_5_Hub

    • 前言
    • Hub命名规则
    • Hub封装好的常用方法
    • Hub常用方法解释
    • 保持状态
    • 前后台交互
    • 结束语
    • 参考文献

前言

上一讲,我们简单的介绍了下Hub的配置以及实现方法,这一将我希望把更多的细节梳理清楚,不至于让大家在细节上面摸不着头脑,理解深了,那么做项目自然就会相对轻松一些。

Hub命名规则

Hub与PersistentConnection很大的区别就是我们可以自己定义我们自己的方法,取我们想取得名字。

Hub的前台调用后台方法的命名规则遵循骆驼命名法,如果不遵循该约定,那么在程序中很有可能报错,在.net中约定大于配置已经是被人们普遍接受的了,它的好处是免去了大量的配置文件,而用一个公用的约定来完成,每个人只要遵循这个约定就不会出篓子。

比如在后台有这么一个方法

  1. public void SendMessageByUserName(string userName)
  2. {
  3. ...
  4. }

那么在前台通过hub.server.sendMessageByUserName("name")调用

如果后台方法改为

  1. public void sendMessageByUserName(string userName)
  2. {
  3. ...
  4. }

在前台则用hub.server.sendmessageByUserName("name")调用以此类推

在后台调用前台方法则无此约定,不区分大小写。因此假设后台你通过Clients.Caller.testHtmlClient();调用前台的方法前台你可以写为hub.client.testHtmlClient(),也可以写为hub.client.testhtmlclient()甚至可以写为hub.client.teStHtMlClIENT()

Hub封装好的常用方法

假如我希望给指定姓名的人发送信息,Hub可以通过唯一的ConnectionId号发送给指定客户端,但是我们一般都是根据数据库中保存用户名或者数据库每条记录的Id进行数据操作。我们希望根据用户名来发送,那么我假设有一个字典保存了ConnectionId和UserName的对应关系

  1. public class MySecondHub : Hub
  2. {
  3. private IDictionary<string, string> _userNames;
  4. public MySecondHub()
  5. {
  6. //TODO:初始化UserNames
  7. }
  8. public void SendMessageByUserName(string userName)
  9. {
  10. //取到所有名字为那么的用户
  11. IList<string> users = _userNames.Where(u => u.Value == userName).Select(u => u.Key).ToList();
  12. Clients.Clients(users).sendMessage("Hi!");
  13. }
  14. }

那么在html页面我们可以通过 hub.server.sendMessageByUserName()调用

  1. <script type="text/javascript">
  2. $(function () {
  3. //创建一个hub服务
  4. var hub = $.connection.myFirstHub;
  5. $.connection.hub.start()
  6. .done(function () {
  7. alert("连接成功!");
  8. })
  9. $("#sayHello").click(function () {
  10. hub.server.sendMessageByUserName("Jake");
  11. });
  12. hub.client.sendMessageByUserName = function(){
  13. ...
  14. };
  15. });
  16. </script>

我们也可以修改前台调用方法的名字

  1. ...
  2. //在前台可以通过sendMessageToGroup()调用
  3. [HubMethodName("SendMessageToGroup")]
  4. public void SendMessageByGroupName(string groupName)
  5. {
  6. Clients.Group(groupName);
  7. }

这样在客户端我们就可以通过sendMessageToGroup()调用SendMessageByGroupName()方法了。

同时,我们传递的参数但可以是字符串也可以是复杂的类型,如:

  1. public class Person
  2. {
  3. public string Name { get; set; }
  4. public int Age { get; set; }
  5. }
  1. public void SayHi(string name,string message)
  2. {
  3. var person = new Person(){Name = name,Message = message};
  4. Clients.Others.sayHi(person);
  5. }

前台代码,点击id为sayHello的按钮触发

  1. ...
  2. $("#sayHello").click(function () {
  3. hub.server.sayHi("jake","hah~");
  4. });
  5. hub.client.sayHi = function(person) {
  6. $(‘#chat‘).append(‘<li><strong>‘ + person.Message + ‘</strong>:‘ + person.Name + ‘</li>‘);
  7. };
  8. ...

之前我们讲到Client.Others.doSomething();可以调用给报包括自己的所有其他客户端doSomething()方法,Hub还有许多其他的方法供我们调用

Hub常用方法解释

  • Clients.Caller:可以与调用者进行通信
  • Clients.Others:可以与除了自己以外所有连接上此Hub的客户端的通信
  • Clients.All:可以与所有连接上此Hub的客户端通信
  • Clients.OthersInGroup:可以与指定组以外的其他连接到Hub的客户端通信
  • Clients.Client:可以与给指定ConnectionId的客户端进行通信
  • Clients.AllExcept:可以与所有连接上此Hub但是除去指定ConnectionId以外的客户端通信
  • Clients.Group:可以与在指定组的客户端通信
  • Clients.User:可以与指定的userId进行通信

    当然他们还有一些重载方法,这里就不一一介绍了,自己去试验下就能明白了。

    PS:这里补充一个小知识,在MVC中已经实现了获取默认的UserId方法

  1. public class PrincipalUserIdProvider : IUserIdProvider
  2. {
  3. public string GetUserId(IRequest request)
  4. {
  5. if (request == null)
  6. throw new ArgumentNullException("request");
  7. if (request.User != null && request.User.Identity != null)
  8. return request.User.Identity.Name;
  9. else return (string) null;
  10. }
  11. }

很多时候我们可能需要自己实现自己的方法,比如userId为登陆的userName,那么我们可以实现IUserIdProvider接口

  1. public class CookiesUserIdProvider : IUserIdProvider
  2. {
  3. public string GetUserId(IRequest request)
  4. {
  5. if (request == null)
  6. throw new ArgumentNullException("request");
  7. Cookie cookie;
  8. if (request.Cookies.TryGetValue("UserName", out cookie))
  9. {
  10. return cookie.Value;
  11. }
  12. else
  13. {
  14. return null;
  15. }
  16. }
  17. }

当然我们还要告诉我们的项目使用我们自定义的提供器,而不是默认的,我们只需要在程序一开始,也就是Global中注册代码保证程序启动时调用即可。

  1. public class MvcApplication : System.Web.HttpApplication
  2. {
  3. protected void Application_Start()
  4. {
  5. ...
  6. //注册我们自己的Id提供器
  7. GlobalHost.DependencyResolver.Register(typeof (IUserIdProvider), () => new CookiesUserIdProvider());
  8. }
  9. }
  10. }

保持状态

在hub中可以通过hub.state保存用户的状态

后台通过Client.Caller 获取前台传递来的参数运行项目断点,可以看到接收到的数据

参数名可以任意写,它是dynamic类型

前后台交互

难道保存状态只有这个用处吗?当然不止,这个状态还可以在某些情况下起到前后台交互的作用。

后台我们让Age++

然后前台在回调方法中我们在控制台中打印age,如果打印的是24,那么证明前后台数据能进行很好的交互而不仅仅是保存一个状态那么简单。

点击按钮后 通过firebug在控制台中可以看到打印出的是24

结束语

今天的文章知识点可能较零散,因为并没有一个实际例子来连接所有的知识,明天开始放假了,如果有时间的话希望能讲一个小例子来巩固一下。

源码下载

由于今天学习的都是些小细节,就不提供源码了。

本文发布至作业部落

参考文献

SignalR Programming in Microsoft ASP.NET pdf 下载

时间: 2024-10-14 02:02:21

一步一步学习SignalR进行实时通信_5_Hub的相关文章

一步一步学习SignalR进行实时通信_8_案例2

原文:一步一步学习SignalR进行实时通信_8_案例2 一步一步学习SignalR进行实时通信\_8_案例2 SignalR 一步一步学习SignalR进行实时通信_8_案例2 前言 配置Hub 建立DrawingHub 页面 javascript 实现效果 结束语 参考文献 前言 这讲分析一个案例,在一个画板上画画实时在其他客户端上显示. 配置Hub 在Startup中进行配置: public void Configuration(IAppBuilder app) { app.MapSign

一步一步学习SignalR进行实时通信_3_通过CORS解决跨域

原文:一步一步学习SignalR进行实时通信_3_通过CORS解决跨域 一步一步学习SignalR进行实时通信\_3_通过CORS解决跨域 SignalR 一步一步学习SignalR进行实时通信_3_通过CORS解决跨域 前言 关于start()的补充 跨域解决方案 JSONP CORS CORS跨域演示 结束语 参考文献 前言 这周工作比较忙,一直没有时间学习SignalR,大致希望一周能写一篇关于SignalR的文章.上一篇用Persistent Connections方式实现了个简单的在线

一步一步学习SignalR进行实时通信_1_简单介绍

原文:一步一步学习SignalR进行实时通信_1_简单介绍 一步一步学习SignalR进行实时通信\_1_简单介绍 SignalR 一步一步学习SignalR进行实时通信_1_简单介绍 前言 SignalR介绍 支持的平台 相关说明 OWIN 结束语 参考文献 前言 本来前几个月想写一系列的关于SignalR的文章,但是由于在做项目,时间非常的紧急,花了1天的时间大致了解了下SignalR,并实现了个在线聊天的小功能,本来记录一系列关于SignalR的文章,没想到写了MVC5使用SignalR进

一步一步学习SignalR进行实时通信_2_Persistent Connections

原文:一步一步学习SignalR进行实时通信_2_Persistent Connections 一步一步学习SignalR进行实时通信\_2_Persistent Connections SignalR 一步一步学习SignalR进行实时通信_2_Persistent Connections 前言 安装 Persistent Connections 映射并配置持久连接 结束语 参考文献 前言 上一篇文章简单的介绍了下SignalR,从此篇文章就开始对SignalR进行剖析.在介绍Persiste

一步一步学习SignalR进行实时通信_7_非代理

目录 一步一步学习SignalR进行实时通信_7_非代理 前言 代理与非代理 建立连接 调用方法 维持状态 从服务器接收 结束语 参考文献 一步一步学习SignalR进行实时通信_7_非代理 标签(空格分隔): SignalR 前言 距离上次写博客已经一个多月了,一直想抽空写,却一直没时间写.现在紧接着要开始毕业设计了,工作的同时还要抽时间完成毕业设计,心也是有些累.由于自己是个.NET迷,自己的工作也是.net开发,老师给的毕业设计百分之八九十都是安卓java相关,虽然之前也学过但是自己还是喜

一步一步学习Vue(十一)

本篇继续学习vuex,还是以实例为主:我们以一步一步学Vue(四)中讲述的例子为基础,对其改造,基于vuex重构一遍,这是原始的代码: todolist.js ; (function () { var list = []; var Todo = (function () { var id = 1; return function (title, desc) { this.title = title; this.desc = desc; this.id = id++; } })(); /** *

一步一步跟我学习lucene(19)---lucene增量更新和NRT(near-real-time)Query近实时查询

这两天加班,不能兼顾博客的更新,请大家见谅. 有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引.对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的: 这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建.对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况

一步一步跟我学习lucene(9)---lucene搜索之拼写检查和相似度查询提示(spellcheck)

suggest应用场景 用户的输入行为是不确定的,而我们在写程序的时候总是想让用户按照指定的内容或指定格式的内容进行搜索,这里就要进行人工干预用户输入的搜索条件了:我们在用百度谷歌等搜索引擎的时候经常会看到按键放下的时候直接会提示用户是否想搜索某些相关的内容,恰好lucene在开发的时候想到了这一点,lucene提供的suggest包正是用来解决上述问题的. suggest包联想词相关介绍 suggest包提供了lucene的自动补全或者拼写检查的支持: 拼写检查相关的类在org.apache.

一步一步学习IdentityServer3 (1)

学习之初: IdentityServer3我自己最开始了解到的就是做一个SSO单点登录,后面发现还有单独的认证服务功能,其实它还可以做APIs的访问控制,资源授权,另外还可以为提供第三方登录,其他的自由定制目前也在学习中. 网络飞速发展的今天,庞大的数据,庞大的用户,庞大的业务,都需要登录的支撑,登录授权完全看作一个单独的一门技术,Web端需要登录,App端需要登录,Api需要授权访问等等,除此以外大型业务系统,子系统之间其实也需要这样一个登陆授权,所以,登录不再是单一的一个功能点了,简单的查询