SignalR簡介
SignalR是什么?
ASP.NET SignalR 是為 ASP.NET 開發人員提供的一個庫,可以簡化開發人員將實時 Web 功能添加到應用程序的過程。實時 Web 功能是指這樣一種功能:當所連接的客戶端變得可用時服務器代碼可以立即向其推送內容,而不是讓服務器等待客戶端請求新的數據。
ASP.NET SignalR是ASP.NET開發人員的一個新庫,可以使開發實時Web功能變得簡單。SignalR允許服務器和客戶端之間的雙向通信。服務器現在可以將內容即時推送到連接的客戶端。SignalR包含用於連接管理(例如連接和斷開事件),連接分組和授權的API。一般情況下,SignalR會使用JavaScript(Ajax長時間輪詢)的長輪詢(long polling)的方式來實現客戶端和服務器通信,隨着Html5中WebSockets出現,SignalR也支持WebSockets通信和支持CORS(跨源資源共享)。另外SignalR開發的程序不僅僅限制於宿主在IIS中,也可以宿主在任何應用程序,包括控制台,客戶端程序和Windows服務等,另外還支持Mono,這意味着它可以實現跨平台部署在Linux環境下。JSONP沒有配置,並且連接不是跨域的,如果客戶端和服務器都支持,則使用WebSocket。
SignalR內部有兩類對象:
Http持久連接(Persisten Connection)對象:
-
Connection表示用於發送單收件人,分組或廣播消息的簡單終端。持久連接API(由PersistentConnection類的.NET代碼表示)為開發人員提供了對SignalR公開的低級通信協議的直接訪問。用來解決長時間連接的功能。還可以由客戶端主動向服務器要求數據,而服務器端不需要實現太多細節,只需要處理PersistentConnection 內所提供的五個事件:OnConnected, OnReconnected, OnReceived, OnError 和 OnDisconnect 即可。
-
Hub(集線器)對象:基於連接API構建的更高級別的管道,允許您的客戶端和服務器直接調用彼此的方法。SignalR像魔術一樣處理跨機器邊界的調度,允許客戶端像本地方法一樣方便地調用服務器上的方法,反之亦然。對於使用遠程調用API(如.NET Remoting)的開發人員來說,使用Hubs通信模型將會很熟悉。使用集線器還允許您將強類型參數傳遞給方法,從而啟用模型綁定。
SignalR將整個信息的交換封裝起來,客戶端和服務器都是使用JSON來溝通的,在服務端聲明的所有Hub信息,都會生成JavaScript輸出到客戶端,.NET則依賴Proxy來生成代理對象,而Proxy的內部則是將JSON轉換成對象。
參考
官網及學習文檔:https://www.asp.net/signalr
github:https://github.com/SignalR
SignalR 參考項目:https://github.com/SignalR/Samples
實戰
工具要求:
- Visual Studio 2013 及以上
- .NET 4.5及以上
- MVC 5及以上
- SignalR版本2及以上
-
使用Visual Studio 2013,創建一個MVC項目
-
通過Nuget安裝SignalR包。
install-package Microsoft.AspNet.SignalR -
安裝SignalR成功后,SignalR庫的腳本將被添加進Scripts文件夾下。具體如下圖所示:

-
在解決方案資源管理器中,右鍵單擊該項目(也可以新建一個類庫),選擇添加 新建文件夾,並添加一個名為Hubs的新文件夾。
用鼠標右鍵單擊該Hubs文件夾,新建一個SignalR Hub Class(v2)類,並創建一個名為Chat .cs。您將使用此類作為將消息發送到所有客戶端的SignalR服務器中心。

-
用下面的代碼替換Chat 類中的代碼。
public class Chat : Hub
{
public void Send(string message)
{
Clients.All.send(message);
}
}
- 創建一個Startup類,如果開始創建MVC項目的時候沒有更改身份驗證的話,這個類會默認添加的,如果已有就不需要重復添加了。按照如下代碼更新Startup類。
using Owin;
using Microsoft.Owin;
[assembly: OwinStartup(typeof(SignalRChat.Startup))]
namespace SignalRChat
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Any connection or hub wire up and configuration should go here
app.MapSignalR();
}
}
}
- 編輯HomeController在Controllers / HomeController.cs中找到的類,並將以下方法添加到類中。此方法返回您將在稍后的步驟中創建的聊天視圖。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace BasicChat.Mvc.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
- 用以下代碼替換Chat.cshtml的內容。
將SignalR和其他腳本庫添加到Visual Studio項目中時,程序包管理器可能會安裝比本主題中顯示的版本更新的SignalR腳本文件版本。確保代碼中的腳本引用與項目中安裝的腳本庫的版本相匹配。
@{
ViewBag.Title = "聊天窗口";
}
<h2>Chat</h2>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion"></ul>
</div>
@section scripts
{
<!--引用SignalR庫. -->
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<!--引用自動生成的SignalR 集線器(Hub)腳本.在運行的時候在瀏覽器的Source下可看到 -->
<script src="~/signalr/hubs"></script>
<script>
$(function () {
// 引用自動生成的集線器代理
var chat = $.connection.serverHub;
// 定義服務器端調用的客戶端sendMessage來顯示新消息
chat.client.sendMessage = function (name, message) {
// 向頁面添加消息
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
};
// 設置焦點到輸入框
$('#message').focus();
// 開始連接服務器
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// 調用服務器端集線器的Send方法
chat.server.send($('#message').val());
// 清空輸入框信息並獲取焦點
$('#message').val('').focus();
});
});
});
// 為顯示的消息進行Html編碼
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
}
效果

SignalR聊天應用程序演示了兩個基本的SignalR開發任務:創建一個集線器作為服務器上的主要協調對象,並使用SignalR jQuery庫來發送和接收消息。
在代碼示例中,ChatHub類從Microsoft.AspNet.SignalR.Hub類派生。從Hub類派生是構建SignalR應用程序的有效方法。您可以在Hub類上創建公共方法,然后通過從網頁中的腳本調用這些方法來訪問這些方法。
在聊天代碼中,客戶端調用ChatHub.Send方法發送一條新消息。集線器通過調用Clients.All.addNewMessageToPage將消息發送給所有客戶端。
所述發送方法演示幾個集線器概念:
- 在集線器上聲明公用方法,以便客戶端可以調用它們。
- 使用Microsoft.AspNet.SignalR.Hub.Clients屬性訪問連接到此集線器的所有客戶端。
- 調用客戶端上的函數(如addNewMessageToPage函數)來更新客戶端。
SignalR和jQuery
代碼示例中的Chat.cshtml視圖文件顯示了如何使用SignalR jQuery庫與SignalR集線器進行通信。代碼中的基本任務是創建對集線器的自動生成代理的引用,聲明服務器可以調用的將內容推送到客戶端的功能,以及啟動連接以將消息發送到集線器。
以下代碼顯示了如何在腳本中創建回調函數。服務器上的集線器類調用此函數將內容更新推送到每個客戶端。對htmlEncode函數的可選調用顯示了一種在將消息內容顯示在頁面之前對其進行HTML編碼的方法,以防止腳本注入。
chat.client.addNewMessageToPage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
};
以下代碼顯示如何打開與集線器的連接。代碼啟動連接,然后傳遞一個函數來處理“聊天”頁面中“ 發送”按鈕上的點擊事件。
這種方法可以確保在事件處理程序執行之前建立連接。
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
按照B/S模式來看,運行程序的時候,Web頁面就與SignalR的服務建立了連接,具體的建立連接的代碼就是:\(.connection.hub.start()。這句代碼的作用就是與SignalR服務建立連接,后面的done函數表明建立連接成功后為發送按鈕注冊了一個click事件,當客戶端輸入內容點擊發送按鈕后,該Click事件將會觸發,觸發執行的操作為: chat.server.send(\)('#message').val())。這句代碼表示調用服務端的send函數,而服務端的Send韓式又是調用所有客戶端的sendMessage函數,而客戶端中sendMessage函數就是將信息添加到對應的消息列表中。這樣就實現了廣播消息的功能了。
ABP實時服務 - 集成SignalR
簡介
在基於ABP創建的項目中,有一個很容易的方式使用 SignalR,那就是使用Abp.Web.SignalR。詳情請參考SignalR文檔。
安裝
使用Nuget安裝[Abp.Web.SignalR(http://www.nuget.org/packages/Abp.Web.SignalR)到你的項目中(通常是你的Web項目)並且在模塊中添加被依賴的模塊:
[DependsOn(typeof(AbpWebSignalRModule))]
public class YourProjectWebModule : AbpModule
{
//...
}
然后,在你的OWIN Startup類中使用 MapSignalR 方法,正如你往常那樣做的:
[assembly: OwinStartup(typeof(Startup))]
namespace MyProject.Web
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
//...
}
}
}
注意:Abp.Web.SignalR 依賴於
Microsoft.AspNet.SignalR.Core。所以,你需要安裝 Microsoft.AspNet.SignalR到你的Web項目中。詳情請參考SignalR文檔。
客戶端
腳本 abp.signalr.js 應該被引用到頁面中。它位於 Abp.Web.Resources 包中(它已經被安裝到啟動模板中)。 我們應該在signalr hubs 后引用它:
<script src="~/signalr/hubs"></script>
<script src="~/Abp/Framework/scripts/libs/abp.signalr.js"></script>
這么做了以后,SignalR就已經恰當的配置和集成到你的項目中了。
建立連接
當 abp.signalr.js 被引用到頁面后,ABP會自動的連接到你的服務器。一般我們都會這么做,但是在某些情況下你不想這樣做。你可以像下面代碼所示禁用自動連接:
<script>
abp.signalr = abp.signalr || {};
abp.signalr.autoConnect = false;
</script>
在這種情況下,你可以手動調用 abp.signalr.connect() 函數來連接服務器。
當客戶端連接到服務器時,全局事件 "abp.signalr.connected" 會被觸發。當連接建立成功的時候,你可以注冊這個事件來采取相應的行動。詳情請參考Javascript函數庫
內置功能
你可以在應用程序中使用所有的SignalR的功能。還有,在 Abp.Web.SignalR 中實現了一些內置功能。
1. 通知
Abp.Web.SignalR 實現了 IRealTimeNotifier 接口來發送實時時間到客戶端。因此,你的用戶可以獲得實時的推送通知。
2. 在線客戶端
ABP提供了 IOnlineClientManager 來取得在線用戶的信息(如:注入IOnlineClientManager以及使用GetByUserIdOrNull, GetAllClients, IsOnline 方法)。為了能夠正常工作,IOnlineClientManager需要一個通信基礎設施。Abp.Web.SignalR 提供了這個基礎設施。如果安裝了SignalR,那么在應用的任何層都可以注入並使用IOnlineClientManager。
3. PascalCase vs. camelCase
Abp.Web.SignalR 使用 CamelCasePropertyNamesContractResolver 重寫了 SignalR's 默認的序列化類 ContractResolver。因此,在服務器端類具有 PascalCase 屬性,而在客戶端為了發送/接受對象,我們使用 camelCase (因為camelCase在JavaScript中更受歡迎)。如果你想在某些程序集中忽略這個,那么你可以將那些程序集添加AbpSignalRContractResolver.IgnoredAssemblies 列表中。
你的SignaR代碼
使用 Abp.Web.SignalR 包也會簡化你的 SignalR代碼。假設我們想要添加一個Hub到你的應用程序中:
public class MyChatHub : Hub, ITransientDependency
{
public IAbpSession AbpSession { get; set; }
public ILogger Logger { get; set; }
public MyChatHub()
{
AbpSession = NullAbpSession.Instance;
Logger = NullLogger.Instance;
}
public void SendMessage(string message)
{
Clients.All.getMessage(string.Format("User {0}: {1}", AbpSession.UserId, message));
}
public async override Task OnConnected()
{
await base.OnConnected();
Logger.Debug("A client connected to MyChatHub: " + Context.ConnectionId);
}
public async override Task OnDisconnected(bool stopCalled)
{
await base.OnDisconnected(stopCalled);
Logger.Debug("A client disconnected from MyChatHub: " + Context.ConnectionId);
}
}
為了使我們的Hub可以簡單的注冊到依賴注入系統中,我們可以實現 ITransientDependency 接口。當然你可以根據你的需求,注冊它為單例模式。我們也使用屬性注入了Session和Logger。
SendMessage是hub的一個方法,它可以被客戶端使用。在這個方法中,我們可以調用所有客戶端的 getMessage函數。正如你看到的那樣,我們可以使用AbpSession來獲得當前的用戶id(如果用戶已經登錄)。為了演示,我們也重寫了 OnConnected 和 OnDisconnected,實際這里是不需要的。
下面是用在Hub中,用來發送/接受信息的客戶端腳本:
var chatHub = $.connection.myChatHub; //get a reference to the hub
chatHub.client.getMessage = function (message) { //register for incoming messages
console.log('received message: ' + message);
};
abp.event.on('abp.signalr.connected', function() { //register for connect event
chatHub.server.sendMessage("Hi everybody, I'm connected to the chat!"); //send a message to the server
});
然后,在我們需要發送信息到服務器時,我們就可以使用 chatHub。詳情請參考SignalR文檔。
Github項目地址:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
本文鏈接:http://www.cnblogs.com/anyushengcms/p/8035924.html
ABP+AdminLTE+Bootstrap Table權限管理系統一期
Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
返回總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期
