2015年3月12日 星期四

Angular 搭配 SignalR


步驟1:安裝SignalR相關套件



自動安裝:  透過NutGet 安裝SignalR套件 
手動安裝:  install-package Microsoft.AspNet.SignalR

步驟2: 建立SignalR Hub類別
















ChatHub.cs
 public class ChatHub : Hub
    {     
        public void send(string name, string message)
        {           
           Clients.All.broadcastMessage(name, message);
        }
    }
   
    請切記如果server端使用broadcastMessage 方式接收訊息,前端也要用同樣的方  式broadcastMessage 去傳送資訊

步驟3: 建立Startup.cs
[assembly: OwinStartup(typeof(singalR2.Startup))]
namespace singalR2
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }
}

    如果您是使用最新版Visual Studio 2015版本,Startup.cs 會自動建立,就不需再自行新增Startup的類別檔。
Chat.html
<body ng-app="chatModel"<!--angular 應用程式-->
    <br />
    <div class="container">
        <div class="row" ng-controller="chatController">
            <div class="col-md-5">
                <div class="panel panel-primary">
                    <div class="panel-heading" id="accordion">
                        <span class="glyphicon glyphicon-comment"></span> Chat
                        <div class="btn-group pull-right">
                            <a type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
                                <span class="glyphicon glyphicon-chevron-down"></span>
                            </a>
                        </div>
                    </div>
                    <div class="panel-collapse collapse" id="collapseOne">
                        <div class="panel-body">
                            <ul class="chat">
<!--  ng-class 條件CSS 可依不同條件顯示不同樣式 -->
<!--  ng-repeat 自動從列舉變數實作出範本的資料列 -->
<!--  ng-if 符合條件判時,才顯示該html段落 -->
<!--  ng-click 按下button 事件觸發 -->

                                <li  ng-class="{'left clearfix': messageObj.name!=name, 'right clearfix': messageObj.name ==name}" ng-repeat="messageObj in allMessage">
                                    <span ng-class="{'chat-img pull-left': messageObj.name!=name,'chat-img pull-right': messageObj.name==name}">
                                        <img src="http://placehold.it/50/FA6F57/fff&text=ME" alt="User Avatar" class="img-circle" ng-if="messageObj.name ==name" />
                                        <img src="http://placehold.it/50/55C1E7/fff&text=U" alt="User Avatar" class="img-circle"  ng-if="messageObj.name!=name" />
                                    </span>
                                    <div class="chat-body clearfix">
                                        <div class="header" ng-if="messageObj.name==name">
                                            <strong class="primary-font">{{messageObj.name}}</strong> <small class="pull-right text-muted">
                                                <span class="glyphicon glyphicon-time"></span>{{messageObj.time}}
                                            </small>
                                        </div>
                                        <div class="header" ng-if="messageObj.name!=name">
                                            <small class=" text-muted"><span class="glyphicon glyphicon-time"></span>{{messageObj.time}}</small>
                                            <strong class="pull-right primary-font">{{messageObj.name}}</strong>
                                        </div>                                    
                                        <p>
                                            {{messageObj.message}}
                                        </p>
                                    </div>
                                </li>
                            </ul>
                        </div>
                        <div class="panel-footer">
                            <div class="input-group">
                                <input type="hidden" ng-model="name" />
                                <input type="hidden" ng-model="group" />
                                <input id="btn-input" type="text" class="form-control input-sm" placeholder="Type your message here..." ng-model="message" />
                                <span class="input-group-btn">
                                    <button class="btn btn-warning btn-sm" id="btn-chat" ng-click="send()">
                                        Send
                                    </button>
                                </span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script src="Scripts/jquery-1.10.2.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.0.js"></script>
    <script src="signalr/hubs"></script> <!-- signalr/hubs 是不存在的檔案,但會自動產生 -->
    <script src="Scripts/angular.min.js"></script>   
    <script src="Scripts/bootstrap.min.js"></script>
    <link href="Content/Chat.css" rel="stylesheet" />
    <link href="Content/bootstrap.css" rel="stylesheet" /></body>

目前範本是使用bootsnipp 提供的範本,直接套用Angular 語法更加方便實現互動式的聊天室, 許多的css特效早期用JQuery語法較傳統,維護上有些不易,但引用angular 語法,特效的處理簡化不少了,例如ng-if, ng-class 就可以將條件判斷用那種CSS ,多麼棒的寫法

注意事項:<script src="signalr/hubs"> 是不存在的檔案,所以很多人忘了加上此script,它會編譯時自動產生

Script 檔案
  <script type="text/javascript">
        var app = angular.module("chatModel", []);
        app.controller("chatController", function ($scope) {
$scope.name = prompt("請輸入您的名字","");
            $scope.allMessage = []; //初始化
            var proxy = $.connection.chatHub;
//建立hub的連線
            $.connection.hub.start().done(function () {
//按下send
                $scope.send = function () {
    // 傳送訊息到server
                    proxy.server.send($scope.name, $scope.message);                   
                };
            });

            proxy.client.broadcastMessage = function (name, message) {
//client 取得來自Server 端的資料後,並逐一加到 $scope.allMessage
                $scope.allMessage.push({
                    "name": name,
                    "message": message,
                    "time": new Date()
                });
                $scope.$apply(); //更新畫面
            };
        });
    </script>

多個網頁連線到此網頁,都會即時分享訊息












SignalR發送單一群組
ChatHub.cs
//加入群組
public void Join(string groupName)
{
   Groups.Add(Context.ConnectionId, groupName);
}
//群組發送
public void groupSend(string group, string message)
{
    //如果發送對象是群組時,只需傳遞一個參數時,client 端接收時,也只會有一個參數
    Clients.Group(group).addNewMessageToPage(message);
}

Script 檔案
<script type="text/javascript">
        var app = angular.module("chatModel", []);
        app.controller("chatController", function ($scope) {
            $scope.allMessage = []; //初始化
            var proxy = $.connection.chatHub;           
            $scope.group = prompt("請輸入您的群組", "");
            $scope.name = prompt("請輸入您的名字","");
            $.connection.hub.start().done(function () {
                //先建立群組
                proxy.server.join($scope.group);
                $scope.send = function () {
                    proxy.server.groupSend($scope.group, $scope.message);
                };
            });

            proxy.client.addNewMessageToPage = function (message) {
                $scope.allMessage.push({
                    "message": message,
                    "time": new Date()
                });
                $scope.$apply(); //更新畫面
            };           
        });
    </script>
 標示 : 只需更改的地方

注意無論ChatHub函式名稱開頭是大寫或小寫,javaScript呼叫ChatHub 的函式,均以小寫開發開頭,例如 Join (雖然大寫),但client端呼叫時,仍需呼叫join($scope.group) 函式。


參考文獻

沒有留言:

張貼留言