需求: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)

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

3.新建一个OWIN Startup类型

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

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

 public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
}

Index.cshtml

@{
Layout = null;
} <!DOCTYPE html>
<script src="~/Scripts/jquery-1.6.4.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.3.0.min.js"></script>
<script src="~/signalr/hubs" type="text/JavaScript"></script>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<script type="text/javascript">
$(function () {
var hello = $.connection.HelloHub;
$.connection.hub.start().done(function () {
$("#btnSubmit").click(function () {
var message = $("#txtMessage").val();
hello.server.Hello(message);
});
}); hello.client.sayHello = function (data) {
$("#content").html(data);
}; }); </script>
</head>
<body>
<div>
<p id="content"></p>
<input id="txtMessage" type="text" />
<input id="btnSubmit" type="button" value="submit" />
</div>
</body>
</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对象打印出来,事实证明,代理确实创建失败了。

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

public class helloHub : Hub
{
public void hello(string message)
{
//Clients.All.hello();
GlobalHost.ConnectionManager.GetHubContext<helloHub>().Clients.All.sayHello("这是服务器转发的内容:" + message);
}
}
<script type="text/javascript">
$(function () {
var hello = $.connection.helloHub;
console.log(hello);
$.connection.hub.start().done(function () {
$("#btnSubmit").click(function () {
var message = $("#txtMessage").val();
hello.server.hello(message);
});
}); hello.client.sayHello = function (data) {
$("#content").html(data);
}; }); </script>

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

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

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

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

jquery.signalR.helper.js

function SignalRHelper(serverHub) {
(function ($) {
var signalRHelper = {
Conn: undefined,
ServerHub: undefined,
ResultData: undefined,
PushData: undefined,
//初始化连接
InitConn: function () {
var self = this;
if (!self.Conn)
self.Conn = $.connection;
},
//创建服务代理
Start: function () {
var self = this;
self.InitConn();
if (!serverHub)
serverHub = "hello";
self.ServerHub = self.Conn[serverHub];
self.Conn.hub.start();
},
//订阅服务端推送的数据
SubscribeServerData: function (clientMethodName,callBack) {
var self = this;
self.ResultData = null;
self.ServerHub.client[clientMethodName] = function (data) {
try {
self.ResultData = JSON.parse(data);
} catch (e) {
self.ResultData = data;
}
callBack(data);
};
},
//上送数据到服务端
PushClientData: function () {
var self = this;
if (arguments.length == 2) {
self.ServerHub.server[arguments[0]](arguments[1]);
} else if (arguments.length == 3) {
self.ServerHub.server[arguments[0]](arguments[1], arguments[2]);
} else if (arguments.length == 4) {
self.ServerHub.server[arguments[0]](arguments[1], arguments[2], arguments[2]);
}
},
}; signalRHelper.Start();
$.SignalRHelper = signalRHelper; })(jQuery);
}

使用方式如下:

@{
Layout = null;
} <!DOCTYPE html>
<script src="~/Scripts/jquery-1.6.4.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.3.0.min.js"></script>
<script src="~/Scripts/jquery.signalR,helper.js"></script>
<script src="~/signalr/hubs" type="text/JavaScript"></script>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<script type="text/javascript">
$(function () {
//var hello = $.connection.helloHub;
//console.log(hello);
//$.connection.hub.start().done(function () {
// $("#btnSubmit").click(function () {
// var message = $("#txtMessage").val();
// hello.server.hello(message);
// });
//}); //hello.client.sayHello = function (data) {
// $("#content").html(data);
//}; window.SignalRHelper("helloHub");
$("#btnSubmit").click(function () {
var msg = $("#txtMessage").val();
$.SignalRHelper.PushClientData("hello", msg);
}); $.SignalRHelper.SubscribeServerData("sayHello", function (data) {
$("#content").html(data);
}); }); </script>
</head>
<body>
<div>
<p id="content"></p>
<input id="txtMessage" type="text" />
<input id="btnSubmit" type="button" value="submit" />
</div>
</body>
</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. 97. Interleaving String (String; DP)

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...

  2. OpenStack的架构详解(转)

    OpenStack既是一个社区,也是一个项目和一个开源软件,它提供了一个部署云的操作平台或工具集.其宗旨在于,帮助组织运行为虚拟计算或存储服务的云,为公有云.私有云,也为大云.小云提供可扩展的.灵活的 ...

  3. js验证input输入正整数 和 输入的金额小数点后保留两位(PC端键盘输入)

    // 验证开头不为零的正整数 WST.zhengZhengShuIn = function (className){ var rex = /^[1-9]{1}[0-9]*$/;//正整数 $(&quo ...

  4. myschool 相思树

    题目描述 一群妖王排成一排站在苦情巨树下,寻找自己的转世恋人.虽然都是妖王,但按照涂山的规定必须进行标号,标号为1的妖王排在最后面,标号为n的妖王排在最前面.每个妖王只有一个妖力值a[i]表示它们现在 ...

  5. script标签的type="test/html"时

    们可以在<script>片断中定义一个被JS调用的代码,但代码又不在页面上显示,这时,我们可以使用下面的方法: 1 <script id="commentTemplate& ...

  6. geoserver 的缓存技术

    geoserver提到的缓存工具共有两个:tilecache和geowebcache.geowebcache是java写的,整合进geoserer中. tilecache则是python写的一个小程序 ...

  7. UI设计是青春饭?今天告诉你真相!

    最近有学员来问,“我想转行学习UI设计,但是听很多人说,UI设计是吃青春饭的,互联网公司是不是只选择年轻的血液而淘汰年纪大的?”今天,我来统一回答一下. UI设计是不是青春饭? 我们先来思考一个问题: ...

  8. workerman使用

    1.start_timer.php(boc) <?php use \Workerman\Worker; use \Workerman\Lib\Timer; require_once '/var/ ...

  9. OpenSCManager

    添加服务程序 执行级别:必须管理员

  10. vue cli+axios踩坑记录+拦截器使用,代理跨域proxy(更新)

    16319 1.首先axios不支持vue.use()方式声明使用,看了所有近乎相同的axios文档都没有提到这一点建议方式 在main.js中如下声明使用 import axios from 'ax ...