首頁  >  文章  >  後端開發  >  詳解Asp.net MVC SignalR來做即時Web聊天實例程式碼

詳解Asp.net MVC SignalR來做即時Web聊天實例程式碼

黄舟
黄舟原創
2017-06-04 09:47:071687瀏覽

本篇文章主要介紹了Asp.net SignalR來做即時Web聊天實例程式碼,具有一定的參考價值,有興趣的小夥伴們可以參考一下

本章和大家分享的內容是使用Signal R框架創建個簡易的群聊功能,主要講解如何在.Net的MVC中使用這個框架,由於這個專案有官方文件(當然全英文),後面也不打算寫分享篇了,主要目的是讓朋友們在需要使用Web即時通訊的時候有更多一種解決方案,畢竟這是微軟主推的一種解決方案之一。

SignalR網路上簡介

#ASP.NET SignalR 是為ASP.NET 開發人員提供的一個函式庫,可以簡化開發人員將即時Web 功能新增至應用程式的過程。即時 Web 功能是指這樣一種功能:當所連接的客戶端變得可用時伺服器程式碼可以立即向其推送內容,而不是讓伺服器等待客戶端請求新的資料。

SignalR當然也提供了非常簡單易用的高階API,讓伺服器端可以單一或批次呼叫客戶端上的JavaScript函數,並且非常方便地進行連接管理,例如客戶端連接到伺服器端,或斷開連接,客戶端分組,以及客戶端授權,使用SignalR都非常容易實現。

SignalR將與客戶端進行即時通訊帶給了ASP .NET 。當然這樣既好用,而且也有足夠的擴充性。以前用戶需要刷新頁面或使用Ajax輪詢才能實現的即時顯示數據,現在只要使用SignalR,就可以簡單實現了。最重要的是您無需重新建立項目,使用現有ASP .NET項目即可無縫使用SignalR。

群組聊天實例效果

咋們先來看看測試案例的效果吧,效果圖:

#介面及其簡單,樣式這裡就不考慮了,主要是展示其用法,這裡涉及到的功能有:

1. 統計在線人數量

2. 顯示線上人數的暱稱和連接方式(本測試案例支援webSockets和longPolling(長連接))

3. 群聊資訊

MVC中如何使用SignalR

首先,我們平常做法建立MVC的Web項目,然後透過Nuget控制台指令: Install-package Microsoft.AspNet.SignalR 加入SignalR的依賴,自動新增的套件如下:

 
 
 
 

並且自動往MVC專案中的Script資料夾中增加相關的js檔案:

jquery.signalR-2.2. 2.min.js

jquery.signalR-2.2.2.js

然後,我們需要在專案一級目錄建立一個檔案名稱為Startup.cs的類,裡面主要內容補全不下:

[assembly: OwinStartup(typeof(Stage.Api.Extend.Startup))]
namespace Stage.Api.Extend
{
  public class Startup
  {
    public void Configuration(IAppBuilder app)
    {
      app.MapSignalR("/chat", new Microsoft.AspNet.SignalR.HubConfiguration
      {
        EnableDetailedErrors = true,
        EnableJavaScriptProxies = true
      });
    }
  }
}

首先我們從上往下分析注意點:

#1.  OwinStartup(Type) 建構子傳遞的是一個類型,而這個類型對應的就是我們所建立的Startup類,這個透過這個建構函式類別標記起始位置;

2.  namespace Stage.Api.Extend 是我專案的命名空間,這個可以隨便定義;

3.  public void Configuration(IAppBuilder app) 函數是固定必須的,這裡程式會先進入這個方法執行裡面的邏輯程式碼;

4.  app.MapSignalR 是擴充的IAppBuilder介面方法,他有多種表現形式,這裡我選擇的是public static IAppBuilder MapSignalR(this IAppBuilder builder, string path, HubConfiguration configuration); ,這裡看有點類似咋們MVC的路由,這裡主要注意的是這個Path參數,在前端頁面的時候需要用到這個路徑;

到这里后台需要的配置其实已经就完成了,下面是具体需要操作的业务逻辑处理类,新建一个类(这里我取名为ChatHub)并继承Hub(这是SignalR框架提供),然后里面的逻辑代码如下:

public class ChatHub : Hub
  {
    //
    public int Num = 10001;
    public static List _Users = new List();

    /// 
    /// 添加聊天人
    /// 
    /// 
    public void AddUser(MoHubUser user)
    {

      user.Id = Context.ConnectionId;
      if (!_Users.Any(b => b.Id == user.Id))
      {
        _Users.Add(user);
      }

      //Clients.All.newUser(user);
      Clients.All.userList(_Users);
    }

    /// 
    /// 发送信息
    /// 
    /// 
    /// 
    public void SendAll(MoHubUser user, string message)
    {
      Clients.All.addNewMessageToPage(user, message);
    }

    /// 
    /// 某个聊天人退出是,通知所有在线人重新加载聊天人数
    /// 
    /// 
    /// 
    public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
    {
      var user = _Users.SingleOrDefault(x => x.Id == Context.ConnectionId);
      if (user != null)
      {
        _Users.Remove(user);
        Clients.All.userList(_Users);
      }
      return base.OnDisconnected(stopCalled);
    }
  }

上面的3个方法分别做了:添加聊天人到List,发送信息到客户端,某个连接失效后通知各个有效的聊天人重新加载信息;这里值得关注的是通过重新 public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) 方法来实现捕获并移除失效连接(这里是聊天人的信息);整篇测试用例通过Context.ConnectionId来保证连接的唯一性,只要有新的链接请求,那么服务端就会分配一个唯一串给这个链接,当客户端关闭页面或关闭链接这个是有就能在OnDisconnected方法中捕获到这个失效的链接的ConnectionId,这样就达到了移除失效聊天人的要求了;为了代码的方便性,这里创建了一个聊天人信息类:

public class MoHubUser
  {

    public string Id { get; set; }
    public string NickName { get; set; }
    public string TransportMethod { get; set; }
  }

到这里后台的聊天室代码就完成了就是这么简单;我们再来看试图中如何来写代码,这里我先给出我的html布局代码:

 @{
  ViewBag.Title = "神牛聊天室 - SignalR";
}

@ViewBag.Title 在线人数:0


      @**@

      客户端这里写法大致有两种选择,一种直接使用生成的代理来操作,一种不用自动生成的代理采用手动创建代理的方式;为了内容的简洁性,这里只简单讲解下自动生成的代理方式,而更多的是分享手动创建代理链接的方式;

      使用生成的代理获取链接

      首先,我们需要通过Script标签来引用一下自动生成代理的路径: 6b7e0e3e57921579395ce622aff978262cacc6d41bbb37262a98f745aa00fbf0 ,注意啦这里的路径/chat对应的就是咋们在前面Startup.cs文件中配置 app.MapSignalR("/chat" 路径,而后面/hubs固定的写法(至少目前我还没更多的试验过),只有先应用了这个~/chat/hubs,才能在后面使用生成的代理,先上段代码:

      var chat = $.connection.chatHub;
          chat.client.newUser = function (user) {
            $("#users").append(' 
    • ' + user.NickName + '[' + user.TransportMethod + ']
    • '); }; chat.client.userList = function (users) { console.log(users); $("#sapnUserTotal").html(users.length); $.each(users, function (i, item) { $("#users").append('
    • [' + item.TransportMethod + '] ' + item.NickName + '(' + item.Id + ')
    • '); }); }; chat.client.addNewMessageToPage = function (user, message) { console.log(user); $("#discussion").append('
    • ' + user.NickName + '[' + user.TransportMethod + ']

      ' + message + '

    • '); }; //connection.hub.start({ transport: ['webSockets', 'longPolling'] }).done(function () { // my.TransportMethod = connection.hub.transport.name; // chat.server.addUser(my); // $('#sendmessage').click(function () { // //console.log(chat); // var content = $.trim($('#message').val()); // if (content.length <= 0) { $('#message').val('').focus(); return; } // chat.server.sendAll(my, content); // $('#message').val('').focus(); // }); //}).fail(function () { // alert("链接聊天室失败,请重新刷新页面。"); //});

      咋们逐步来解析下代码注意点:

      1.  var chat = $.connection.chatHub; 这里的chatHub对应的就是咋们创建的并继承Hub的ChatHub类,由于js变量开头都是小写,所以这里是chatHub,这句活就表示链接到咋们后端了ChatHub类了,然后就可以使用里面的方法啦(这种有点类似于早期的webform中某种ajax请求的写法)

      2. 通过chat.client.xxx来接收服务端通知的消息,而这个xxx对应的方法名称和咋们后端的Clients.All.xxx,本章实例对应的是:chat.client.userList = function (users){}对应Clients.All.userList(_Users);这样后端就能直接通知客户端的对应方法了;注意这里我后端Clients.All用的是通知全部客户端的意思,如果您需要通知指定的链接需要用到的是: T Client(string connectionId); 方法

      3. chat.client是后端调用客户端,那相对的chat.server就是客户端请求服务端,和上面一样通过chat.server.xxx来指定请求的服务端方法,注意这个时候服务端方法指的是继承类Hub的子类的公共方法(本篇对应的是:chat.server.sendAll(my, content)对应ChatHub.cs文件中的 public void SendAll(MoHubUser user, string message) 函数)

      4.  connection.hub.start({ transport: ['webSockets', 'longPolling'] }) 来指定运行的交互协议

      以上就是使用生成代理的方式,按照上面的注意点来写应该不是问题;

      使用手动创建反向代理来链接

      不采用生成的代码的方式,我们只需要修改前端就行了,后台代码不用变或设置不用变动;首先我们把上面说的Script引用自动代理的代码去掉,因为这个时候不需要了,我们还是先上代码:

      var my = { NickName: "神牛001", TransportMethod: "" };
          var connection = $.hubConnection("/chat/hubs");
          var chat = connection.createHubProxy('chatHub');
      
          chat.on("userList", function (users) {
            console.log(users);
            $("#sapnUserTotal").html(users.length);
            $("#users").html("");
            $.each(users, function (i, item) {
              $("#users").append(' 
    • [' + item.TransportMethod + '] ' + item.NickName + '(' + item.Id + ')
    • '); }); }); chat.on("addNewMessageToPage", function (user, message) { console.log(user); $("#discussion").append('
    • ' + user.NickName + '[' + user.TransportMethod + ']

      ' + message + '

    • '); var p = document.getElementById('discussion'); //p.scrollTop = p.scrollHeight; p.scrollTop = 999999; }); var nickName = prompt("请输入一个昵称:", my.NickName); my.NickName = nickName.length > 0 ? nickName : my.NickName; $('#displayname').val(nickName); $('#message').focus(); connection.start({ transport: ['webSockets', 'longPolling'] }).done(function () { my.TransportMethod = connection.transport.name; //console.log(my.TransportMethod); chat.invoke("addUser", my); $('#sendmessage').click(function () { var content = $.trim($('#message').val()); if (content.length <= 0) { $('#message').val('').focus(); return; } chat.invoke("sendAll", my, content); $('#message').val('').focus(); }); });

      同样列出如下注意点:

      1.  var connection = $.hubConnection("/chat/hubs"); 创建链接,这里的path同样对应后端的 app.MapSignalR("/chat" ,路径保持一致

      2.  var chat = connection.createHubProxy('chatHub'); 来创建反向代理链接,这里的name:chatHub对应的是后端的ChatHub类名称

      3. 通过on("xxx",function(){})函数来绑定服务端通知客户端的事件,xxx对应Clients.All.xxx中的xxx

      4.  connection.start({ transport: ['webSockets', 'longPolling'] }) 來設定允許的連結方式,並開始連結

      #5. connection.transport .name來取得連結的方式名稱,預設start不設定的話有這麼多種:webSockets,foreverFrame,serverSentEvents,longPolling

      6. chat.invoke("xxx", param1, param2)透過invoke來映射繼承類別Hub的類別的公共方法,這裡實例對應的是: chat.invoke("sendAll", my, content) 對應public void SendAll(MoHubUser user, string message)

      寫在最後

      #

      以上是詳解Asp.net MVC SignalR來做即時Web聊天實例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

      陳述:
      本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn