需求:Asp.Net MVC 开发客户端,实现与服务器端实时通信。

众所周知,Web开发是基于http的请求响应模型,每次刷新都需要客户端(浏览器)主动发起请求,那么,这个问题怎么解?Asp.Net SignalR是一个Asp.Net 下的类库,可以在Asp.Net  的Web项目中实现实时通信,完美解决这个问题。关于SignalR具体的介绍可以查阅其他资料,或者查看官方文档:http://signalr.net/,今天我写这篇文章的主要目的是记录学习过程,以及对SignalR的使用进行一个简单的封装。

开发工具:VS2013

1.首先,新建一个空的Asp.Net MVC项目,然后按照官方网站上提供的NuGet命令 Install-Package Microsoft.AspNet.SignalR 安装SignalR。

2.新建一个SignalR集线器类(V2.1)

  1. public class HelloHub : Hub
  2. {
  3. public void Hello(string message)
  4. {
  5. //Clients.All.hello();
  6. GlobalHost.ConnectionManager.GetHubContext<HelloHub>().Clients.All.sayHello("这是服务器转发的内容:" + message);
  7. }
  8. }

3.新建一个OWIN Startup类型

  1. public class Startup
  2. {
  3. public void Configuration(IAppBuilder app)
  4. {
  5. // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
  6. app.MapSignalR();
  7. }
  8. }

4.新建一个HomeController,以及对应的View

  1. public class HomeController : Controller
  2. {
  3. // GET: Home
  4. public ActionResult Index()
  5. {
  6. return View();
  7. }
  8. }

Index.cshtml

  1. @{
  2. Layout = null;
  3. }
  4.  
  5. <!DOCTYPE html>
  6. <script src="~/Scripts/jquery-1.6.4.min.js"></script>
  7. <script src="~/Scripts/jquery.signalR-2.3.0.min.js"></script>
  8. <script src="~/signalr/hubs" type="text/JavaScript"></script>
  9. <html>
  10. <head>
  11. <meta name="viewport" content="width=device-width" />
  12. <title>Index</title>
  13. <script type="text/javascript">
  14. $(function () {
  15. var hello = $.connection.HelloHub;
  16. $.connection.hub.start().done(function () {
  17. $("#btnSubmit").click(function () {
  18. var message = $("#txtMessage").val();
  19. hello.server.Hello(message);
  20. });
  21. });
  22.  
  23. hello.client.sayHello = function (data) {
  24. $("#content").html(data);
  25. };
  26.  
  27. });
  28.  
  29. </script>
  30. </head>
  31. <body>
  32. <div>
  33. <p id="content"></p>
  34. <input id="txtMessage" type="text" />
  35. <input id="btnSubmit" type="button" value="submit" />
  36. </div>
  37. </body>
  38. </html>

准备工作都已经完成了,接下来,直接访问,网页跳转后,查看调试信息,报了一个错。Cannot read property 'client' of undefined(无法读取未定义的属性'client'),这是怎么回事?

其实,细心的人都已经发现了,我们之前Index.cshtml中引入js文件的时候,引入了一个虚拟目录<script src="~/signalr/hubs" type="text/JavaScript"></script>,这个目录是用来干嘛的?查看调试器中我们请求的资源不难发现,多了一个hubs的js文件,而这个js文件中为我们自动生成了代理,而创建代理的时候使用的Hub的名称为helloHub(小驼峰命名法),与我们创建的Hub的名称HelloHub(大驼峰命名法)不一致,导致代理创建失败。

为了证明我的猜想,我将hello对象打印出来,事实证明,代理确实创建失败了。

问题已经找到了,就很好解决,修改我们的类名称,采用小驼峰命名法。批注:方法名称也存在同样的问题,所以一并改为小驼峰命名法。

  1. public class helloHub : Hub
  2. {
  3. public void hello(string message)
  4. {
  5. //Clients.All.hello();
  6. GlobalHost.ConnectionManager.GetHubContext<helloHub>().Clients.All.sayHello("这是服务器转发的内容:" + message);
  7. }
  8. }
  1. <script type="text/javascript">
  2. $(function () {
  3. var hello = $.connection.helloHub;
  4. console.log(hello);
  5. $.connection.hub.start().done(function () {
  6. $("#btnSubmit").click(function () {
  7. var message = $("#txtMessage").val();
  8. hello.server.hello(message);
  9. });
  10. });
  11.  
  12. hello.client.sayHello = function (data) {
  13. $("#content").html(data);
  14. };
  15.  
  16. });
  17.  
  18. </script>

再次,请求网页,代理创建成功!

测试发送内容,完全没有问题。不完美的地方是C#类名称与方法名称都是采用大驼峰命名法,改成了小驼峰是不是有点不爽,其实我们还可以通过特性的方式重命名就可以解决这个问题,就不做演示了,代码如下:

  1. [HubName("helloHub")]
  2. public class HelloHub : Hub
  3. {
  4. [HubMethodName("hello")]
  5. public void Hello(string message)
  6. {
  7. //Clients.All.hello();
  8. GlobalHost.ConnectionManager.GetHubContext<HelloHub>().Clients.All.sayHello("这是服务器转发的内容:" + message);
  9. }
  10. }

以上演示的内容都是原生的写法,但是每次调用都这么写还是挺麻烦的,所以在此基础上做了一个JQuery的封装:

jquery.signalR.helper.js

  1. function SignalRHelper(serverHub) {
  2. (function ($) {
  3. var signalRHelper = {
  4. Conn: undefined,
  5. ServerHub: undefined,
  6. ResultData: undefined,
  7. PushData: undefined,
  8. //初始化连接
  9. InitConn: function () {
  10. var self = this;
  11. if (!self.Conn)
  12. self.Conn = $.connection;
  13. },
  14. //创建服务代理
  15. Start: function () {
  16. var self = this;
  17. self.InitConn();
  18. if (!serverHub)
  19. serverHub = "hello";
  20. self.ServerHub = self.Conn[serverHub];
  21. self.Conn.hub.start();
  22. },
  23. //订阅服务端推送的数据
  24. SubscribeServerData: function (clientMethodName,callBack) {
  25. var self = this;
  26. self.ResultData = null;
  27. self.ServerHub.client[clientMethodName] = function (data) {
  28. try {
  29. self.ResultData = JSON.parse(data);
  30. } catch (e) {
  31. self.ResultData = data;
  32. }
  33. callBack(data);
  34. };
  35. },
  36. //上送数据到服务端
  37. PushClientData: function () {
  38. var self = this;
  39. if (arguments.length == 2) {
  40. self.ServerHub.server[arguments[0]](arguments[1]);
  41. } else if (arguments.length == 3) {
  42. self.ServerHub.server[arguments[0]](arguments[1], arguments[2]);
  43. } else if (arguments.length == 4) {
  44. self.ServerHub.server[arguments[0]](arguments[1], arguments[2], arguments[2]);
  45. }
  46. },
  47. };
  48.  
  49. signalRHelper.Start();
  50. $.SignalRHelper = signalRHelper;
  51.  
  52. })(jQuery);
  53. }

使用方式如下:

  1. @{
  2. Layout = null;
  3. }
  4.  
  5. <!DOCTYPE html>
  6. <script src="~/Scripts/jquery-1.6.4.min.js"></script>
  7. <script src="~/Scripts/jquery.signalR-2.3.0.min.js"></script>
  8. <script src="~/Scripts/jquery.signalR,helper.js"></script>
  9. <script src="~/signalr/hubs" type="text/JavaScript"></script>
  10. <html>
  11. <head>
  12. <meta name="viewport" content="width=device-width" />
  13. <title>Index</title>
  14. <script type="text/javascript">
  15. $(function () {
  16. //var hello = $.connection.helloHub;
  17. //console.log(hello);
  18. //$.connection.hub.start().done(function () {
  19. // $("#btnSubmit").click(function () {
  20. // var message = $("#txtMessage").val();
  21. // hello.server.hello(message);
  22. // });
  23. //});
  24.  
  25. //hello.client.sayHello = function (data) {
  26. // $("#content").html(data);
  27. //};
  28.  
  29. window.SignalRHelper("helloHub");
  30. $("#btnSubmit").click(function () {
  31. var msg = $("#txtMessage").val();
  32. $.SignalRHelper.PushClientData("hello", msg);
  33. });
  34.  
  35. $.SignalRHelper.SubscribeServerData("sayHello", function (data) {
  36. $("#content").html(data);
  37. });
  38.  
  39. });
  40.  
  41. </script>
  42. </head>
  43. <body>
  44. <div>
  45. <p id="content"></p>
  46. <input id="txtMessage" type="text" />
  47. <input id="btnSubmit" type="button" value="submit" />
  48. </div>
  49. </body>
  50. </html>

每天,进步一点点....

SignalR简单封装的更多相关文章

  1. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

  2. FMDB简单封装和使用

    工具:火狐浏览器+SQLite Manager插件 ; Xcode; FMDB库; 效果: 项目地址: https://github.com/sven713/PackFMDB 主要参考这两篇博客: 1 ...

  3. Android--Retrofit+RxJava的简单封装(三)

    1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...

  4. okhttp3 get post 简单封装

    最近打算在新项目中使用 okhttp3, 简单封装了一下异步 get post 因为 CallBack 也是在子线程中执行,所以用到了 Handler public class MyOkHttpCli ...

  5. python网页请求urllib2模块简单封装代码

    这篇文章主要分享一个python网页请求模块urllib2模块的简单封装代码. 原文转自:http://www.jbxue.com/article/16585.html 对python网页请求模块ur ...

  6. 对pymysql的简单封装

    #coding=utf-8 #!/usr/bin/python import pymysql class MYSQL: """ 对pymysql的简单封装 "& ...

  7. iOS开发——UI篇OC篇&UITableView简单封装

    UITableView简单封装 UITableView时iOS开发中使用最多也是最重的一个UI空间,其实在App Store里面的%80以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也 ...

  8. iOS sqlite 增删改查 简单封装(基于 FMDB)

    /** *  对 sqlite 的使用进行简单封装,仅涉及简单的单表 增删改查 * *  基于 FMDB * *  操作基于 model ,数据库表字段与 model 属性一一对应,对 model 整 ...

  9. ADO简单封装(MFC)

    简单封装了一下,不是很严谨. /************************************************************************/ /* INSTRUC ...

随机推荐

  1. MyBatis核心配置文件详解

    ------------------------siwuxie095                                     MyBatis 核心配置文件详解         1.核心 ...

  2. 对象导航查询和OID查询(补)

    ----------------siwuxie095                                 对象导航查询         以客户和联系人为例(一对多)     1.应用场景 ...

  3. oracle pl/sql程序

    简单的pl/sql程序 declare begin dbms_output.put_line('hello world'); end; 什么是PL/SQL? pl/sql(Procedure lang ...

  4. SSH三大框架需要的jar包

    1. Struts2框架 * struts-2.3.24\apps\struts2-blank\WEB-INF\lib\*.jar -- Struts2需要的所有jar包 * struts2-spri ...

  5. Spring框架的特点

    1. 为什么要学习Spring的框架 * 方便解耦,简化开发 * Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理 * AOP编程的支持 * Spring提供面向切面 ...

  6. 什么是RNA-Seq (RNA Sequencing)

    什么是RNA-Seq (RNA Sequencing) 2011-07-14 ~ ADMIN 随着ome为词尾的各种组学的出现,转录组学已经成为了人们了解生物信息的一个重要组成部分.人们使用了许多办法 ...

  7. tp5在apache下能访问,但放到nginx下报404

    index index.php index.html index.htm; if ( -f $request_filename) { break; } if ( !-e $request_filena ...

  8. ejb 和pojo , jboss 和 tomcat

    EJB(企业JavaBeans)是普通JavaBeans的一种提升和规范,因为企业信息系统开发中需要一个可伸缩的性能和事务.安全机制,这样能保证企业系统平滑发展,而不是发展到一种规模重新更换一套软件系 ...

  9. 移动文件流的读写指针---fseek

    函数原型:int fseek(FILE *stream,long offset,int origin) stream:文件指针, offset:偏移量,正数表示正向偏移,负数表示负向偏移.origin ...

  10. Git使用1

    1.先配置本地Git E:\personal>git config –-global user.name "lewy" E:\personal>git config – ...