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

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

SignalR


前言

这周工作比较忙,一直没有时间学习SignalR,大致希望一周能写一篇关于SignalR的文章。上一篇用Persistent Connections方式实现了个简单的在线聊天功能,这次我们继续深入学习。

关于start()的补充

在上一篇文章里前台的html页面我们通过几句javascript创建了一个,代码如下,也可以下载上次的源码。

  1. <!DOCTYPE html>
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <title>persistent connections</title>
  5. <script src="Scripts/jquery-1.10.2.min.js"></script>
  6. <script src="Scripts/jquery.signalR-2.0.0.min.js"></script>
  7. </head>
  8. <body>
  9. <h1>Echo service</h1>
  10. <div>
  11. <input type="text" id="text" />
  12. <button id="send">Send</button>
  13. </div>
  14. <script>
  15. $(function () {
  16. var connection = $.connection("/echo");
  17. connection.logging = true;
  18. connection.received(function (data) {
  19. $("body").append(data + "<br />");
  20. });
  21. connection.error(function (err) {
  22. alert("存在一个错误. \n" +
  23. "Error: " + err.message);
  24. });
  25. connection.start().done(function () {
  26. $("#send").click(function () {
  27. connection.send($("#text").val());
  28. $("#text").val("").focus();
  29. });
  30. });
  31. });
  32. </script>
  33. </body>
  34. </html>

这里需要做些说明:通过代码var connection = $.connection("/echo");

我们创建了一个连接,通过connection.start().done()来开启连接并在连接完成时处理我们需要处理的事件。

如果你将以下代码

  1. connection.start().done(function () {
  2. connection.send('Hi');
  3. });

分成2部分写,如:

  1. connection.start();
  2. connection.send('Hi');

那么你必须注意:

虽然你在connection.send()之前调用了connection.start()开启了连接,但是connection.start()是一个异步方法,意味着有可能你在调用connection.send()时connection并未开启,那么项目将会报错。

正确方法如之前代码所示,再加上一段开启失败的代码:

  1. var connection = $.connection("/echo");
  2. connection.start(function() {
  3. // 连接开启成功才会进入这里
  4. connection.send("Hi");
  5. }).fail(function() {
  6. //连接开启失败则进入这里
  7. alert("服务开启失败");
  8. });

跨域解决方案

上篇文章里有同学问到跨域的问题,那么在接下来的时间我将会带着大家一起学习。

在SignalR解决跨域,有两种方式:第一种是JSONP,第二种是CORS。

JSONP

如果你的服务必须要支持老版本的浏览器,那么JSONP是唯一选择,否则处于安全的考虑这并不被推荐,具体什么安全因素我并不知晓(有同学知道的话可以说明下),基于快速学习的情况下,我们无需纠缠于此。服务器默认会禁用此功能,我们可以通过初始化时提供一个ConnectionConfiguration对象并设置EnableJSONP属性为true来激活此功能。

  1. public class Startup
  2. {
  3. public void Configuration(IAppBuilder app)
  4. {
  5. var config = new ConnectionConfiguration()
  6. {
  7. EnableJSONP = true
  8. };
  9. app.MapSignalR<EchoConnection>("/echo", config);
  10. }
  11. }

我想这几句代码应该很好理解,我们在前面提到过MapSignalR<TConnection>()有许多重载方法,这是另一个重载方法通过提供一个ConnectionConfiguration对象进行相关配置。

CORS

CORS是一个独立的框架,它可以很方便的解决跨域问题,通过Nuget安装

安装命令:Install-Package microsoft.owin.cors

CORS是通过Owin实现的,所以我们需要在项目启动时对他进行一些配置,和做SignalR映射一样实在Startup中进行配置。

  1. public class Startup
  2. {
  3. public void Configuration(IAppBuilder app)
  4. {
  5. //app.MapSignalR<EchoConnection>("/echo");
  6. app.Map("/echo",
  7. map => {
  8. map.UseCors(CorsOptions.AllowAll);
  9. map.RunSignalR<EchoConnection>();
  10. }
  11. );
  12. }
  13. }

代码应该也不难,这次我们通过app.Map()进行映射,第一个参数是映射的地址,第二个参数是一个lambda表达式,通过UseCors(CorsOptions.AllowAll)允许允许跨域。

CORS跨域演示

JSONP我不做演示了有兴趣的可以自己尝试下,接下来我这里做一个通过CORS来进行跨域聊天。首先我讲上次的项目复制一份,省得再重新打代码,并将复制出来的项目名称由SignalR_1改为SignalR_2_CORS

项目目录如下图所示:



省得麻烦,我把SignalR_1部署在IIS上面,这就充当了 一个远程的SignalR服务。



部署成功后,如图所示:



此时我们讲SignalR_2_CORS项目稍作修改

1. 将Startup中的映射删去,此时SignalR_2_CORS已不做SignalR服务器了,只做客户端来连接SignalR_1提供的服务



2. 将echo中的var connection = $.connection("/echo");改为

var connection = $.connection("http://127.0.0.1:8083/echo");



然后运行SignalR_2_CORS中的echo页面,结果如图所示:



出现了一个错误,这个错误提示是我们自己写的



因为我们的SignalR_1并没有允许跨域连接,那么在SignalR_2_CORS中当然无法连接,接下来我们在项目一中允许跨域连接。



重新编译项目一后再刷新下SignalR_1echo.html页面,注意我们这个页面地址



然后刷新下SignalR_2_CORS的页面,注意这个地址



连接成功,没有报错了,发送个消息试试看(●ˇ∀ˇ●)



结束语

这里通过CORS实现了SignalR的跨域问题,跨域如此简单赶快试试吧 。

注意:在通过Nuget安装CORS包时,我这边提示了Unable to find package 'Microsoft.AspNet.Cors'我已经FQ了,所以这个应该不是需要FQ才能下载,但是在Nuget页面中搜索确实有这个包,具体什么原因引起的我也不清楚,如果你有碰到这个问题请下载解压并添加引用即可,由于Microsoft.AspNet.Cors依赖于Microsoft.AspNet.Cors,所以里面的2个包都要添加引用

源码下载

本文发布至作业部落

参考文献

SignalR Programming in Microsoft ASP.NET pdf 下载

一步一步学习SignalR进行实时通信_3_通过CORS解决跨域的更多相关文章

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

    一步一步学习SignalR进行实时通信\_1_简单介绍 SignalR 一步一步学习SignalR进行实时通信_1_简单介绍 前言 SignalR介绍 支持的平台 相关说明 OWIN 结束语 参考文献 ...

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

    原文:一步一步学习SignalR进行实时通信_8_案例2 一步一步学习SignalR进行实时通信\_8_案例2 SignalR 一步一步学习SignalR进行实时通信_8_案例2 前言 配置Hub 建 ...

  3. 一步一步学习SignalR进行实时通信_9_托管在非Web应用程序

    原文:一步一步学习SignalR进行实时通信_9_托管在非Web应用程序 一步一步学习SignalR进行实时通信\_9_托管在非Web应用程序 一步一步学习SignalR进行实时通信_9_托管在非We ...

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

    原文:一步一步学习SignalR进行实时通信_7_非代理 一步一步学习SignalR进行实时通信\_7_非代理 SignalR 一步一步学习SignalR进行实时通信_7_非代理 前言 代理与非代理 ...

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

    原文:一步一步学习SignalR进行实时通信_5_Hub 一步一步学习SignalR进行实时通信\_5_Hub SignalR 一步一步学习SignalR进行实时通信_5_Hub 前言 Hub命名规则 ...

  6. 一步一步学习SignalR进行实时通信_6_案例

    原文:一步一步学习SignalR进行实时通信_6_案例 一步一步学习SignalR进行实时通信\_6_案例1 一步一步学习SignalR进行实时通信_6_案例1 前言 类的定义 各块功能 后台 上线 ...

  7. 一步一步学习SignalR进行实时通信_4_Hub

    原文:一步一步学习SignalR进行实时通信_4_Hub 一步一步学习SignalR进行实时通信\_4_Hub SignalR 一步一步学习SignalR进行实时通信_4_Hub 前言 创建Hub 配 ...

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

    原文:一步一步学习SignalR进行实时通信_2_Persistent Connections 一步一步学习SignalR进行实时通信\_2_Persistent Connections Signal ...

  9. 从.Net到Java学习第十二篇——SpringBoot+JPA提供跨域接口

    从.Net到Java学习系列目录 最近又撸了半个月的前端代码,做app离线存储,然后又花了一周去将过去的wcf项目转webapi,java又被落下了,总感觉我特么像斗地主中的癞子牌,变来变去..... ...

随机推荐

  1. EC读书笔记系列之13:条款25 考虑写出一个不抛异常的swap函数

    记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于cla ...

  2. Android 中退出程序的几种方法

    1.finish()方法 finish是Activity的类,仅仅针对Activity,当调用finish()时,只是将活动推向后台,并没有立即释放内存,活动的资源并没有被清理:调用finish()方 ...

  3. 常用DOM整理

    常用DOM整理   前言: html为document搭建了一棵DOM树,这棵树就是有一系列Node节点所构成的.他为我们定义了文档的结构. Node类型: Node.ELEMENT_NODE(1); ...

  4. struts2笔记03-ActionContext

    1.概念 ActionContext是action的上下文,它包括action执行所需要的对象.struts2对每一个action都会创建一个新的ActionContext实例,同Action一样,是 ...

  5. JAVA工具_PinyinConv

    package cn.chh.utils; /** * 获得每个字符的首字母 * @author CHH * @since 2013-01-21 * @bugs 不支持多音字处理 */ public ...

  6. [问题解决] initAndListen: 10309 Unable to create/open lock file: /data/db/mongod.lock

    错误: 在linux下开启mongoDB的 $ >bin: ./mongod 时报错:initAndListen: 10309 Unable to create/open lock file: ...

  7. IC卡存储器介绍

    自从80年代中期出现IC电话卡后,基本已取代了原来流行的电话磁卡,磁卡存在存在严重的安全问题,已逐步淘汰.即使IC电话卡,也不能算很安全,卡内所有数据只要有简单的读写装置并按时序操作都能读取,事实上电 ...

  8. Dot模板的使用小结2

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Objective-C官方文档翻译 Block

    版权声明:原创作品,谢绝转载!否则将追究法律责任. 一个Objective-c类定义了一个对象结合数据相关的行为.有时候,这使得他有意义的表达单个任务或者单元的行为.而不是集合的方法. blocks是 ...

  10. 深度学习工具caffe具体安装指南

    caffe安装指南-吐血整理 前言: 在一台系统环境较好的linux机器上能够非常easy的安装caffe,可是假设系统本身非常旧,又没有GPU的话.安装就太麻烦了,全部都得从头做起,本文档旨在尽可能 ...