SignalR
html
這周工做比較忙,一直沒有時間學習SignalR,大體但願一週能寫一篇關於SignalR的文章。上一篇用Persistent Connections方式實現了個簡單的在線聊天功能,此次咱們繼續深刻學習。java
在上一篇文章裏前臺的html頁面咱們經過幾句javascript建立了一個,代碼以下,也能夠下載上次的源碼。jquery
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <title>persistent connections</title> <script src="Scripts/jquery-1.10.2.min.js"></script> <script src="Scripts/jquery.signalR-2.0.0.min.js"></script></head><body> <h1>Echo service</h1> <div> <input type="text" id="text" /> <button id="send">Send</button> </div> <script> $(function () { var connection = $.connection("/echo"); connection.logging = true; connection.received(function (data) { $("body").append(data + "<br />"); }); connection.error(function (err) { alert("存在一個錯誤. \n" + "Error: " + err.message); }); connection.start().done(function () { $("#send").click(function () { connection.send($("#text").val()); $("#text").val("").focus(); }); }); }); </script></body></html>
這裏須要作些說明:經過代碼var connection = $.connection("/echo");
咱們建立了一個鏈接,經過connection.start().done()
來開啓鏈接並在鏈接完成時處理咱們須要處理的事件。
若是你將如下代碼json
connection.start().done(function () { connection.send('Hi');});
分紅2部分寫,如:跨域
connection.start();connection.send('Hi');
那麼你必須注意:
雖然你在connection.send()
以前調用了connection.start()
開啓了鏈接,可是connection.start()
是一個異步方法,意味着有可能你在調用connection.send()
時connection並未開啓,那麼項目將會報錯。
正確方法如以前代碼所示,再加上一段開啓失敗的代碼:瀏覽器
var connection = $.connection("/echo");connection.start(function() { // 鏈接開啓成功纔會進入這裏 connection.send("Hi");}).fail(function() { //鏈接開啓失敗則進入這裏 alert("服務開啓失敗");});
上篇文章裏有同窗問到跨域的問題,那麼在接下來的時間我將會帶着你們一塊兒學習。
在SignalR解決跨域,有兩種方式:第一種是JSONP,第二種是CORS。安全
若是你的服務必需要支持老版本的瀏覽器,那麼JSONP是惟一選擇,不然處於安全的考慮這並不被推薦,具體什麼安全因素我並不知曉(有同窗知道的話能夠說明下),基於快速學習的狀況下,咱們無需糾纏於此。服務器默認會禁用此功能,咱們能夠經過初始化時提供一個ConnectionConfiguration對象並設置EnableJSONP屬性爲true來激活此功能。服務器
public class Startup{ public void Configuration(IAppBuilder app) { var config = new ConnectionConfiguration() { EnableJSONP = true }; app.MapSignalR<EchoConnection>("/echo", config); }}
我想這幾句代碼應該很好理解,咱們在前面提到過MapSignalR<TConnection>()
有許多重載方法,這是另外一個重載方法經過提供一個ConnectionConfiguration
對象進行相關配置。app
CORS是一個獨立的框架,它能夠很方便的解決跨域問題,經過Nuget安裝
安裝命令:Install-Package microsoft.owin.cors
CORS是經過Owin實現的,因此咱們須要在項目啓動時對他進行一些配置,和作SignalR映射同樣實在Startup中進行配置。
public class Startup{ public void Configuration(IAppBuilder app) { //app.MapSignalR<EchoConnection>("/echo"); app.Map("/echo", map => { map.UseCors(CorsOptions.AllowAll); map.RunSignalR<EchoConnection>(); } ); }}
代碼應該也不難,此次咱們經過app.Map()
進行映射,第一個參數是映射的地址,第二個參數是一個lambda表達式,經過UseCors(CorsOptions.AllowAll)
容許容許跨域。
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_1的echo.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個包都要添加引用