1. 程式人生 > >ASP.Net MVC SignalR的應用

ASP.Net MVC SignalR的應用

ASP.Net MVC SignalR的應用

最近做的一個MVC專案有個模組是要使用即時通訊實現彈幕效果。既要考慮通訊的實時性也要考慮伺服器效能和資源消耗,所幸專案對瀏覽器的版本沒有要求。所以我最先想到用WebSocket來實現,在查詢資料時, 看到 SignalR 這個技術,也就是本專題所討論的物件。在拜讀了 史上最全面的SignalR系列教程-認識SignalR ,算是對 SignalR有一個簡單的認識,SignalR 是 .NET平臺為我們提供的一種簡潔高效智慧的實時資訊互動技術,SignalR 比 WebSocket 還要簡單,這簡直是我的福音。所以我直接一個Demo開始嘗試。

SignalR

關於SignalR的介紹這邊就不多贅述,可以去看我上面說的這篇博文史上最全面的SignalR系列教程-認識SignalR 或者直接看Microsoft文件 Introduction to SignalR,SignalR可用於任何即時性的功能;

Demo :使用SignalR和MVC 5實現實時聊天

通過第一部分的介紹,相信大家對SignalR有初步的認識,接下來直接上手一個Demo來看看(我的開發環境:VS2019 + .net 4.6.2 + MVC 5)。步驟參考微軟教程 Tutorial: Real-time chat with SignalR 2 and MVC 5。

  1. 使用Visual Studio 2019 建立一個MVC工程-SignalRMvcChat


建立ASP.NET Web應用程式


配置專案

  1. 選擇MVC,然後身份驗證上,選擇“無身份驗證”,然後單擊“建立”。


  1. 在專案上右擊-新增新建項,選擇 Installed > Visual C# > Web > SignalR and then 選擇 SignalR Hub Class (v2).


  1. 將類命名為ChatHub並將其新增到專案中。 此步驟將建立ChatHub.cs集線器類檔案,並將一組支援SignalR的指令碼檔案和程式集引用新增到專案:


  1. 用以下程式碼替換新建的ChatHub.cs類檔案中的程式碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;

namespace SignalRMvcChat
{
    public class ChatHub : Hub
    {
        public void Send(string name, string message)
        {
            Clients.All.addNewMessageToPage(name, message);
        }
    }
}
  1. 在專案上,右鍵選擇 新增>類,命名為Startup.cs,並用以下程式碼替換新建的Startup.cs類檔案中的程式碼:
using Owin;
using Microsoft.Owin;
[assembly: OwinStartup(typeof(SignalRMvcChat.Startup))]
namespace SignalRMvcChat
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }
}

注意: SignalR 框架使用Owin元件,每一個使用的OWin元件的Web框架都需要一個Startup入口類,用來宣告OWin元件:
1.專案會自動掃描程式集根下的名為Startup的類,來作為入口類;
2.通過新增 [assembly: OwinStartup(typeof(SignalRChat.Startup))] 標籤標記入口類;
3.如果你的啟動類不在當前名稱空間下,需要在Web.config中新增節點: ,來指定啟動類;

  1. 在Home控制器中新增一個方法,來返回下面聊天步驟所使用的頁面:在 HomeController.cs 中新增以下方法:
public ActionResult Chat()
{
    return View();
}
  1. 在Views/Home中新增Chat檢視,並用以下程式碼替換到新建的檢視檔案中:(注意:檢視中所引用的signalR指令碼可能跟你實際安裝的版本不一樣,這裡需要你根據實際安裝的版本進行修改)
@{
    ViewBag.Title = "Chat";
}
<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 {
    <!--jQuery庫是必需的,預設情況下在_Layout.cshtml引用. -->
    <!--引用SignalR庫. -->
    <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>
    <!--引用自動生成的SignalR 集線器(Hub)指令碼.在執行的時候在瀏覽器的Source下可看到. -->
    <script src="~/signalr/hubs"></script>
    <script>
        $(function () {
            // 引用自動生成的集線器代理 必須用小寫字母開頭.
            var chat = $.connection.chatHub;

            // 定義伺服器端呼叫的客戶端addNewMessageToPage來處理接收到的訊息.
            chat.client.addNewMessageToPage = function (name, message) {
                // 將訊息新增到ul上.
                $('#discussion').append('<li><strong>' + htmlEncode(name)
                    + '</strong>: ' + htmlEncode(message) + '</li>');
            };

            // 獲取使用者名稱.
            $('#displayname').val(prompt('Enter your name:', ''));

            // 設定焦點到輸入框.
            $('#message').focus();

            // 開始連線伺服器 done函式表明建立連線成功後為傳送按鈕註冊了一個click事件.
            $.connection.hub.start().done(function () {
                $('#sendmessage').click(function () {
                    // 呼叫伺服器端集線器的Send方法 也要小寫開頭.
                    chat.server.send($('#displayname').val(), $('#message').val());
                    // 清空輸入框資訊並獲取焦點.
                    $('#message').val('').focus();
                });
            });
        });

        // 這個可選功能將html-encodes訊息顯示在頁面上.
        function htmlEncode(value) {
            var encodedValue = $('<div />').text(value).html();
            return encodedValue;
        }
    </script>
}

執行一下看看效果:

  • 在工具欄中,啟用“指令碼除錯”,然後點選“執行”按鈕以在瀏覽器上除錯(注意啟動專案要設成當前的這個MVC專案)。


-進入聊天頁面 ~/Home/Chat


1

可能出現的問題:

The following errors occurred while attempting to load the app.


The following errors occurred while attempting to load the app.
- No assembly found containing an OwinStartupAttribute.
- No assembly found containing a Startup or [AssemblyName].Startup class.
To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of "false" in your web.config.
To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.

以上的問題出現在我第一次執行的時候,看著錯誤提示是沒有找到 OwinStartupAttribute ,然後跟著提示在web.config的appSetting中新增如下的節點:

<appSettings>
    <add key="owin:AutomaticAppStartup" value="false" />
    ...
</appSettings>

執行居然真的就不報錯,但是問題更大條了。在聊天頁面並沒有生成SignalR代理的hubs的指令碼檔案,出現了Uncaught TypeError: Cannot read property 'client' of undefined錯誤



對比了微軟官方使用 SignalR 步驟,才認識到 SignalR 框架使用Owin元件,一定要指定一個Startup入口類,我是少了以上步驟6,在添加了Startup.cs類之後,問題解決了(新增的Startup.cs類的名稱空間為應用程式根目錄的名稱,去掉之前web.config中加入的錯誤程式碼)。對於SignalR代理物件異常,大家還可以看下這篇文章, SignalR代理物件異常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的結論,只要注意自動生成的集線器指令碼中的代理名稱和服務端方法都是小寫字母開頭,呼叫的時候使用小寫就可以避免這個問題。

檢視原始碼

以上就是今天給大家的分享全部內容了,祝大家元旦快樂!

參考文章

  • 史上最全面的SignalR系列教程-認識SignalR
  • Tutorial: Real-time chat with SignalR 2 and MVC 5
  • SignalR代理物件異常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的結論