使用ASP.NET SignalR設計聊天室

by Vivid 26. 二月 2014 05:32
.NET Magazine國際中文電子雜誌
者:許薰尹
稿:張智凱
文章編號:N140214502
出刊日期:2014/02/26
開發工具:Visual Studio 2012 Ultimate
版本:.NET Framework 4.5ASP.NET SignalR 2.0 
 
SignalR是一個為ASP.NET所設計,整合用戶端與伺服端的開放原始程式碼(Open Source)的程式庫,讓用戶端瀏覽器和ASP.NET伺服端的元件能夠建立雙向溝通,以非同步的方式交換訊息。最重要的是它並不受限在單一、無狀態的請求/回應的資料交換方式(如HTTP),現在伺服端也可以主動的將資訊推送到已建立連結的用戶端,連線建立後直到明確關閉為止。因此,ASP.NET SignalR特別適合用來撰寫像網頁聊天室、股票及時監控系統,甚至是互動性遊戲等等之類的網頁程式。
參考下圖,伺服端可以利用SignalR送訊息到用戶端;用戶端可以透過Hub代理程式傳送訊息到伺服端,請參考下圖所示:
clip_image002
圖 1:SignalR適合用來建立雙向溝通程式。
透過ASP.NET SignalR程式庫,你可以同時廣播訊息傳送到所有建立連結的用戶端,也可以傳送訊息給特定的用戶端。ASP.NET SignalR適用於Web情境,用戶端需要搭配jQuery、伺服端需要使用ASP.NET,底層則是使用HTML Web Socket技術,只要應用程式所在的系統支援Web Socket協定,ASP.NET SignalR便會自動使用它來進行溝通。第一次連結到ASP.NET SignalR時,使用HTTP協定,接著便會自動升級,改用Web Socket來通訊。
在微軟的平台中,伺服端的元件若要使用WebSocket協定的話,目前只有Windows Server 2012 或 Windows 8.x,以及 .NET Framework 4.5版以上的作業統才支援。同時目前也有許多的瀏覽器並不支援Web Socket,不過你不用擔心,ASP.NET SignalR也提供不支援Web Socket的舊瀏覽器一些替代方案,例如在舊瀏覽器中改用Server Sent Event技術,並將這些實作細節隱藏起來,讓你感覺不到它的存在。
ASP.NET SignalR程式庫中包含了一些應用程式介面(API),讓開發的動作更為簡單。重要的模型有兩個:
  • · Persistent Connection:包裝在Microsoft.AspNet.SignalR.Core.dll組件中的PersistentConnection類別。代表要傳送訊息的端點(Endpoint),透過它傳送訊息給單一用戶端、群組使用者,或對已連線的用戶端進行訊息廣播。
  • · Hubs:讓用戶端與伺服端可以雙向溝通的類別,用戶端可以直接呼叫伺服端的程式碼,反之亦然,伺服端可以直接呼叫用戶端的程式碼。
本篇文章介紹如何立用Visual Studio 2012與ASP.NET SignalR 2.0函式庫來建立一個網頁聊天室應用程式。

使用Visual Studio 2012建立專案

啟動Visual Studio 2012開發環境,從「File」-「New」-「Project」,在「New Project」對話盒中,設定上方的清單的.NET Framework版本為「.NET Framework 4.5」;選取左方「Installed」清單-「Templates」-「Visual C#」程式語言,從「Web」分類中,選取「ASP.NET MVC Web Application」。設定專案名稱為「demo」,設定專案存放路徑之後,按下「OK」鍵,請參考下圖所示:
clip_image004
圖 2:建立ASP.NET MVC Web Application應用程式專案。
在「New ASP.NET MVC 4 Project」視窗中,選取「Basic」範本,然後按下畫面右下方的「OK」按鈕建立專案,請參考下圖所示:
clip_image006
圖 3:建立Basic範本專案。

安裝jQuery程式庫

因為ASP.NET SignalR依賴於jQuery程式庫,因此我們先更新網站專案中的jQuery程式庫。Visual Studio 2012開發工具提供一個NuGet套件管理工具可以很容易地安裝 jQuery套件。
從Visual Studio 2012開發工具-「Solution Explorer」- 專案 - 「Manage NuGet Packages」開啟「Manage NuGet Packages」對話盒,選取左上方「Online」清單項目。因為jQuery是一個非常熱門的JavaScript函式庫,因此,通常此函式庫會出現在「Online」清單項目中的第一個,接著按下「Install」按鈕做安裝。在本文撰寫時最新的版本為2.1.0版。請參考下圖所示:
clip_image008
圖 4:安裝 jQuery套件。

安裝Microsoft.AspNet.SignalR程式庫

下一步是安裝 Microsoft.AspNet.SignalR程式庫,在本文撰寫時,最新的Microsoft.AspNet.SignalR套件版本是2.0.2版。從Visual Studio 2012開發工具-「Solution Explorer」- 專案 - 「Manage NuGet Packages」開啟「Manage NuGet Packages」對話盒,選取左上方「Online」清單項目, 在右上方文字方塊中輸入「Microsoft.AspNet.SignalR」關鍵字,搜尋「Microsoft.AspNet.SignalR」,然後按下「Install」按鈕做安裝。請參考下圖所示:
clip_image010
圖 5:安裝Microsoft.AspNet.SignalR程式庫。
完成安裝之後,專案之中會自動加入ASP.NET SignalR相關組件的參考,例如Microsoft.AspNet.SignalR.Core.dll、Microsoft.AspNet.SignalR.SystemWeb.dll,以及相依的Microsoft.Web.Infrastructure.dll、Microsoft.Owin.dll、Microsoft.Owin.Host.SystemWeb.dll、Microsoft.Owin.Security.dll等等組件的參考。

建立伺服端HUB類別

我們先從伺服端著手,建立伺服端的HUB類別。從Visual Studio 2012開發工具-「Solution Explorer」- 專案名稱上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」,開啟「Add New Item」對話盒,從右上方文字方塊輸入「Class」搜尋,選取「Class」,設定名稱為「MyHub」,然後按下「Add」按鈕,建立新類別,請參考下圖所示:
clip_image012
圖 6:建立伺服端HUB類別。
在MyHub類別程式檔案最上方引用Microsoft.AspNet.SignalR與Microsoft.AspNet.SignalR.Hubs命名空間:
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
在MyHub類別上方,加上HubName attribute,設定名稱為「MyHub」,此外MyHub類別必需要繼承定義在Microsoft.AspNet.SignalR命名空間下的Hub抽象類別,此類別提供一些方法用來連接到Microsoft.AspNet.SignalR.Hub以及和SignalR連線溝通,以及一些關於用戶端資訊的屬性:
namespace demo {
[HubName( "MyHub" )]
public class MyHub : Hub {
public void Send( string name , string message ) {
Clients.All.sendMsg( name , message );
}
}
}
伺服端若要送資料到用戶端,可以使用Hubs類別的Clients屬性。Clients屬性的型別(type)為dynamic,能夠參考動態產生的物件。Clients屬性也包含一個參考指向伺服端的物件。因此範例中的MyHub類別內,設計一個Send方法,這個方法接收兩個參數,分別是傳送訊息的用戶端別名,以及聊天訊息內容,並將訊息廣播,透過Clients屬性的All屬性,取得所有已連線的用戶端,然後叫用定義在用戶端的sendMsg方法讓用戶端可以更新頁面。未來用戶端的網頁便可以叫用伺服端的這個public方法,來傳送訊息給伺服端。

路由組態

伺服端的程式碼設計完成之後,你需要將ASP.NET路由(Routing)對應到SignalR函式庫,在你利用NuGet管理員安裝完ASP.NET SignalR套件之後,專案之中有個readme.txt檔案(這個檔案將會存放在你的「專案\packages\Microsoft.AspNet.SignalR.2.0.2」資料夾之中),部分的說明內容如下圖,其中描述路由的設定資訊,以及一個Startup類別的程式碼:
clip_image014
圖 7:Startup類別的程式碼。
在ASP.NET SignalR 2.0版之後,利用OWIN技術來提供跨伺服器平台的支援,OWIN是一個中間層程式,定義網站伺服器與網站應用程式之間的標準,以減少網站伺服器與網站應用程式的相依性。因此若使用ASP.NET SignalR 2.0版,需要在網站之中註冊OWIN啟動類別,以便在OWIN啟動過程中,設定路由與SignalR的對應資訊。
根據readme.txt文件的說明,首先在App_Start資料夾中新增一個Startup.cs 類別。從Visual Studio 2012開發工具-「Solution Explorer」- 「App_Start」名稱上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」,開啟「Add New Item」對話盒,從右上方文字方塊輸入「Class」搜尋,選取「Class」,設定名稱為「Startup」,然後按下「Add」按鈕,建立新類別。在Startup類別程式檔案最上方引用Owin命名空間:
using Owin;
參考readme.txt中的程式,加入Configuration方法到Startup類別,目前的程式碼看起來如下:
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace demo.App_Start {
  public class Startup {
    public void Configuration( IAppBuilder app ) {
      app.MapSignalR( );
    }
  }
}
 
在專案根目錄下的web.config組態檔案之中,<appSettings>區段內加入以下加組態,設定OWIN啟動類別的資訊:
<add key="owin:AppStartup" value="demo.App_Start.Startup, demo" />
目前<appSettings>區段的內容看起來如下:
<appSettings>
<add key="owin:AppStartup" value="demo.App_Start.Startup, demo" />
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

加入HomeController控制器類別

設計聊天室程式,為專案加入一個HomeController控制器類別。從Visual Studio 2012開發工具-「Solution Explorer」視窗- 專案 -「Controllers」目錄上方按滑鼠右鍵,從快捷選單選擇「Add」- 「Controller」項目,開啟「Add Controller」對話盒。在「Controller name」地方輸入控制器的名稱為「HomeController」,「Template」選擇「Empty MVC controller」,然後按下「Add」按鈕,請參考下圖所示:
clip_image016
圖 8:加入HomeController控制器類別。
Visual Studio 2012會自動加入以下程式碼,HomeController類別之中包含一個Index方法,用來回傳Index 檢視:
namespace demo.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/
        public ActionResult Index()
        {
            return View();
        }
    }
}
 

 

建立Index檢視

用戶端是透過SignalR jQuery 程式庫和伺服端的Signal Hub溝通的,設計的步驟包含:
  • l 宣告一個代理程式參考到Signal Hub。
  • l 宣告一個方法,例如sendMsg讓伺服端呼叫,以更新用戶端頁面的內容。
  • l 建立連線,連結到Hub。
接著我們來建立檢視(Index View)。將游標停留在HomeController控制器程式設計畫面Index方法之中,按滑鼠右鍵,從快捷選單選取「Add View」,請參考下圖所示:
clip_image018
圖 9:建立Index檢視。
在「Add View」對話盒中,設定「View name」為「Index」。勾選「Use a layout or master page:」核取方塊,然後選取「~/Views/Shared/_Layout.cshtml」檔案,接著按下「Add」按鈕,請參考下圖所示:
clip_image020
圖 10:設定View。
Visual Studio 2012便會在Views\Home目錄下,新增一個Home.cshtml檔案,在檔案之中加入以下程式碼:
@{
    ViewBag.Title = "Chat";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>愛哈拉聊天室</h2>
<div id="connect">
    <input type="text" id="txtUserName" value="" placeholder="請輸入名稱" autofocus="autofocus" />
    <input type="button" id="btnConnect" value="進入聊天室" />
</div>

<div id="chatArea" style="visibility: hidden">
    <div id="nickname"></div>
    訊息:
    <input type="text" id="txtMsg" autofocus="autofocus" />
    <input type="button" id="send" value="Send" />
    <ul id="result">
    </ul>
</div>
@section scripts{
    <script src="~/Scripts/jquery.signalR-2.0.2.min.js"></script>
      <script src="~/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            var userName = '匿名';
            $("#btnConnect").click(function () {
                userName = $("#txtUserName").val();
                $("#nickname").text("用戶名稱 : " + userName);
                $("#connect").css("display", "none");
                $("#chatArea").css("visibility", "visible");
                $('#txtMsg').val('').focus();
            });
            var chat = $.connection.MyHub;
            chat.client.sendMsg = function (userName, msg) {
                var item = "<li>" + userName + ":" + msg + "</li>";
                $('#result').prepend(item);
            };
            $.connection.hub.start().done(function () {
                $('#send').click(function () {
                     var msg = $('#txtMsg').val();                   
                     chat.server.send(userName, msg);                    
                });
            });
        });
    </script>
}
 
重點程式說明如下,在@section scripts區段之中,引用ASP.NET SignalR程式庫:
<script src="~/Scripts/jquery.signalR-2.0.2.min.js"></script>
參考ASP.NET SignalR程式庫readme.txt的內容,加入以下<script>標籤,引用的src是動態產生的:
<script src="~/signalr/hubs"></script>
$.connection物件是定義在SignalR程式庫之中,而$.connection.MyHub物件是一個動態物件(Dynamic Object),程式動態產生,透過「~/signalr/hubs」<script>標籤的參考,動態地插入至用戶端網頁之中。範例中利用$.connection.MyHub宣告一個代理物件(Proxy)參考到Hub,接著定義一個sendMsg方法,在回呼(Callback)函式之中,更新頁面,若收到從伺服端傳送的訊息,就將收到的訊息顯示在網頁id為「result」的<ul>項目之中。
$.connection.hub.start()方法一執行便和伺服端建立連線,連線建立完成之後,利用done()註冊回呼函式,以處理後續的動作。在本範例之中,註冊id為「send」的<Button>項目之click事件,只要按下按鈕,就把文字方塊中的訊息送到伺服端。

建置專案與測試聊天室

最後我們便可以來測試一下聊天室的運作。選取Visual Studio 2012「Build」-「Build Solution」建置專案。開啟兩個瀏覽器,或兩個瀏覽器,下圖分別開啟Internet Explorer 與Chrome瀏覽器,一開始的畫面如下:
clip_image022
圖 11:測試聊天室。
你可以在文字方塊之中輸入用戶的名稱,請參考下圖所示:
clip_image024
圖 12:進入聊天室。
不管是任一個瀏覽器按下「Send」按鈕傳送訊息到伺服器,另一個瀏覽器會馬上顯示出訊息的內容,請參考下圖所示:
clip_image026
圖 13:廣播以及顯示收到的廣播訊息內容。

啟用日誌監控運作

ASP.NET SignarlR提供簡單的監控能力,你可以在程式中啟用日誌的功能來監控SignalR的運作,語法為:
$.connection.hub.logging = true;
啟用之後,只要在瀏覽器開啟除錯工具,就可以從Console看到日誌資料,下圖是Chrome瀏覽器執行的結果:
clip_image028
圖 14:啟用日誌監控運作。
此外你可以利用瀏覽器的除錯工具來觀察範例執行的結果,以下是Chrome瀏覽器的除錯畫面(只要在瀏覽器上按下F12鍵就可以開啟除錯工具),從除錯工具中,你可以看到用戶端從伺服端下載一個hubs.js檔案,這個檔案是ASP.NET SignalR程式庫動態產生的,請參考下圖所示:
clip_image030
圖 15:利用瀏覽器的除錯工具來觀察範例執行的結果。

設定啟動類別

除了利用本文範例所述在web.confg檔案<appSettings>區段註冊之外,也可以利用assembly attribute。例如將上述範例<appSettings>區段OWIN設定註解:
<appSettings>
  <!--<add key="owin:AppStartup" value="demo.App_Start.Startup, demo" />-->
  <add key="webpages:Version" value="2.0.0.0" />
  <add key="webpages:Enabled" value="false" />
  <add key="PreserveLoginUrl" value="true" />
  <add key="ClientValidationEnabled" value="true" />
  <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
 
修改MyHub類別,在MyHub類別檔案中加上assembly attribute,指明啟動類別的名稱:
[assembly: OwinStartup( typeof( demo.App_Start.Startup ) )]
namespace demo {
  [HubName( "MyHub" )]
  public class MyHub : Hub {
    public void Send( string name , string message ) {
      Clients.All.sendMsg( name , message );
    }
  }
}

總結

ASP.NET SignalR是一套為ASP.NET程式設計師所設計的程式庫,簡化網站用戶端與伺服端之間溝通的方式,能夠建立及時、雙向的通訊功能,讓我們可以不管底層的複雜運作,而能輕鬆地寫出雙向溝通的網站應用程式。
參考資源

Tags:

.NET Magazine國際中文電子雜誌 | ASP.NET MVC | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List