ASP.NET Core SignalR 入門

来源:https://www.cnblogs.com/xyh9039/archive/2023/07/02/17520659.html
-Advertisement-
Play Games

本章將和大家分享使用 SignalR 生成實時應用的基礎知識。通過本文您將學習如何:使用ASP.NET Core SignalR + MVC + Vue 2.x + require 最終創建一個正常運行的簡易聊天應用。 ...


本章將和大家分享使用 SignalR 生成實時應用的基礎知識。通過本文您將學習如何:使用ASP.NET Core SignalR + MVC + Vue 2.x + require 最終創建一個正常運行的簡易聊天應用。

廢話不多說,我們直接來看一個Demo,Demo的目錄結構如下所示:

本Demo的Web項目為ASP.NET Core Web 應用程式(目標框架為.NET 7.0) MVC項目。  

1、創建 SignalR 中心

中心是一個類,用作處理客戶端 - 伺服器通信的高級管道。

可通過已連接客戶端調用 SendMessage,以向所有客戶端發送消息。

using Microsoft.AspNetCore.SignalR;

namespace SignalRChat.Hubs
{
    /// <summary>
    /// Hub 類管理連接、組和消息
    /// </summary>
    public class ChatHub : Hub
    {
        /// <summary>
        /// 可通過已連接客戶端調用 SendMessage,以向所有客戶端發送消息
        /// </summary>
        public async Task SendMessage(string user, string message)
        {
            //Clients.All 向所有的客戶端發送消息(服務端調用客戶端)
            //ReceiveMessage 是客戶端監聽的方法
            await Clients.All.SendAsync("ReceiveMessage", user, message);

            /*
                // 常用方法
                // 給所有人發送消息
                await Clients.All.SendAsync("ReceiveMessage", data);

                // 給組裡所有人發消息
                await Clients.Group("Users").SendAsync("ReceiveMessage", data);

                // 給調用方法的那個人發消息
                await Clients.Caller.SendAsync("ReceiveMessage", data);

                // 給除了調用方法的以外所有人發消息
                await Clients.Others.SendAsync("ReceiveMessage", data);

                // 給指定connectionId的人發消息
                await Clients.User(connectionId).SendAsync("ReceiveMessage", data);

                // 給指定connectionId的人發消息
                await Clients.Client(connectionId).SendAsync("ReceiveMessage", data);

                // 給指定connectionId的人發消息,同時指定多個connectionId
                await Clients.Clients(IReadOnlyList<> connectionIds).SendAsync("ReceiveMessage", data);
            */
        }
    }
}

2、配置 SignalR

必須將 SignalR 伺服器配置為將 SignalR 請求傳遞給 SignalR。 將以下突出顯示(標紅)的代碼添加到 Program.cs 文件。

using SignalRChat.Hubs;

namespace SignalRChat
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            //服務註冊(往容器中添加服務)
            // Add services to the container.
            builder.Services.AddControllersWithViews();
            builder.Services.AddSignalR(); //SignalR

            var app = builder.Build();

            //配置Http請求處理管道
            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            //配置MVC路由
            app.MapControllerRoute(
                name: "areas",
                pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            app.MapHub<ChatHub>("/chatHub"); //SignalR

            app.Run();
        }
    }
}

以上突出顯示(標紅)的代碼將 SignalR 添加到 ASP.NET Core 依賴關係註入和路由系統。

3、添加 SignalR 客戶端代碼

chat.js 文件,核心 JavaScript 代碼如下:

//第一個參數:載入依賴模塊,可以是require_config中定義的短模塊名,也可以是完整的模塊路徑(去掉.js尾碼名,根目錄為require_config中設置的baseUrl)
//第二個參數:執行載入完後的回調函數
require(['../common/base', 'jquery', 'signalr'], function (base, $, signalR) {
    let axios = base.axios;

    var vm = new base.vue({
        el: '#app', //掛載點
        mixins: [base.mixin], //混入,類似基類的概念
        data: {
            connectionSignalR: '', //SignalR連接
            user: '',
            message: '',
            msgList: []
        },
        //created鉤子函數
        created: function () {
            this.initSignalR(); //初始化SignalR
        },
        //mounted鉤子函數
        mounted: function () {
            //console.log('This is index mounted');
        },
        //方法
        methods: {
            //初始化SignalR
            initSignalR: function () {
                var _this = this;
                //創建連接
                _this.connectionSignalR = new signalR.HubConnectionBuilder()
                    .withUrl("/chatHub")
                    .configureLogging(signalR.LogLevel.Error)
                    .build();
                /*
                    日誌等級:
                    signalR.LogLevel.Error:錯誤消息。 Error僅記錄消息。
                    signalR.LogLevel.Warning:有關潛在錯誤的警告消息。 日誌 Warning 和 Error 消息。
                    signalR.LogLevel.Information:無錯誤的狀態消息。 日誌 Information 、 Warning 和 Error 消息。
                    signalR.LogLevel.Trace:跟蹤消息。 記錄所有內容,包括中心和客戶端之間傳輸的數據。
                */

                //監聽中心(服務端)發送的消息(服務端調用客戶端)
                //ReceiveMessage 是服務端調用客戶端的方法名
                _this.connectionSignalR.on("ReceiveMessage", function (user, message) {
                    _this.msgList.push({
                        user: user,
                        message: message
                    });
                });

                //啟動連接
                _this.connectionSignalR.start().then(function () {
                    //啟動連接後需要立即執行的邏輯
                    //document.getElementById("sendButton").disabled = false;
                }).catch(function (err) {
                    return console.error(err.toString());
                });
            },
            //發送消息
            sendMsg: function () {
                var _this = this;

                if (_this.message) {
                    //向中心(服務端)發送消息(客戶端調用服務端)
                    //SendMessage 是服務端定義的的方法
                    _this.connectionSignalR.invoke("SendMessage", _this.user, _this.message).catch(function (err) {
                        return console.error(err.toString());
                    });
                    _this.message = ''; //發送完清空消息
                }
            },
        }
    });
});

公共腳本文件代碼如下:

其中 require_config.js 文件代碼如下:

//主要用來配置模塊的載入位置(設置短模塊名)
require.config({
    baseUrl: '/js/lib', //設置根目錄
    paths: { //如果沒有設置根目錄則需要填寫完整路徑
        'vue': 'vue',
        'axios': 'axios',
        'jquery': 'jquery-3.6.3',
        'signalr': 'signalr',
        //paths還有一個重要的功能,就是可以配置多個路徑,如果遠程cdn庫沒有載入成功,可以載入本地的庫,如下:
        //'jquery': ['http://libs.baidu.com/jquery/2.0.3/jquery', '/js/lib/jquery-3.6.3'],
    }
});

其中 base.js 文件代碼如下:

//define用來自定義模塊
//第一個參數:載入依賴模塊,可以是require_config中定義的短模塊名,也可以是完整的模塊路徑(去掉.js尾碼名)
//第二個參數:執行載入完後的回調函數
define(['vue', 'axios', '../components/buttonCounter'], function (vue, axios, buttonCounter) {
    //TODO 此處可以處理一些公共的邏輯
    //vue.component('component-a', { /* ... */ }); //全局註冊組件
    //vue.mixin({...}); //全局混入

    /*
        定義組件名的方式有兩種:
        1、使用 kebab-case (短橫線分隔命名)
            當使用 kebab-case (短橫線分隔命名) 定義一個組件時,你也必須在引用這個自定義元素時使用 kebab-case,例如 <my-component-name>
        
        2、使用 PascalCase (首字母大寫命名) 
            當使用 PascalCase (首字母大寫命名) 定義一個組件時,你在引用這個自定義元素時兩種命名法都可以使用。
            也就是說 <my-component-name> 和 <MyComponentName> 都是可接受的。
            註意,儘管如此,直接在 DOM (即非字元串的模板) 中使用時只有 kebab-case 是有效的。    
    */

    //Vue.component(...) 的第一個參數為組件名。      
    vue.component('button-counter', buttonCounter); //全局註冊

    return {
        vue: vue,
        axios: axios,

        //Vue混入
        mixin: {
            //數據
            data: function () {
                return {
                    domain: '', //功能變數名稱
                }
            },
            //組件
            components: {

            },
            //created鉤子函數
            created: function () {
                //console.log('This is base created');
                var _this = this;
                _this.getDomain();
            },
            //mounted鉤子函數
            mounted: function () {
                console.log('This is base mounted');
            },
            //方法
            methods: {
                //測試
                doTest: function () {
                    console.log('This is base doTest');
                },
                //獲取功能變數名稱
                getDomain: function () {
                    var _this = this;
                    _this.domain = 'http://localhost:5296';
                },
            }
        },
    };
});

控制器和視圖文件代碼如下:

其中 HomeController 控制器代碼如下:

using Microsoft.AspNetCore.Mvc;
using SignalRChat.Models;
using System.Diagnostics;

namespace SignalRChat.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();
        }
    }
}

其中佈局頁 _Layout.cshtml 視圖文件代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - SignalRChat</title>

    <script src="/js/lib/require.js"></script>
    <script src="/js/common/require_config.js"></script>
    @await RenderSectionAsync("header", required: false)
</head>
<body>
    <div class="container">
        @RenderBody()
    </div>
    @await RenderSectionAsync("footer", required: false)
</body>
</html>

其中 Index.cshtml 視圖文件代碼如下:

@{
    ViewData["Title"] = "Home Page";
}

<div id="app">
    <template>
        <p>
            User:<input v-model="user" type="text" />
        </p>
        <p>
            Message: <input v-model="message" type="text" />
        </p>
        <p>
            <button v-on:click="sendMsg">發送</button>
        </p>
        <hr />
        <ul>
            <li v-for="(item, index) in msgList" :key="index">
                {{ item.user }} says {{ item.message }}
            </li>
        </ul>
    </template>
</div>

@section footer{
    <script src="/js/pageScript/chat.js"></script>
}

4、運行應用

此處我使用的是 .NET Core CLI  命令行的方式來運行應用,如下所示:

打開兩個瀏覽器實例,分別訪問:http://localhost:5296/ , 運行結果如下:

選擇任一瀏覽器,輸入名稱和消息,然後點擊“發送”按鈕:

可以發現,兩個頁面上會立即顯示名稱和消息。 

更多關於 ASP.NET Core SignalR 的相關知識可參考微軟官方文檔:https://learn.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-7.0&tabs=visual-studio

至此本文就全部介紹完了,如果覺得對您有所啟發請記得點個贊哦!!!

 

Demo源碼:

鏈接:https://pan.baidu.com/s/13ppUjr0h2dse5vnw5uiZ9Q 
提取碼:qm2a

此文由博主精心撰寫轉載請保留此原文鏈接:https://www.cnblogs.com/xyh9039/p/17520659.html

版權聲明:如有雷同純屬巧合,如有侵權請及時聯繫本人修改,謝謝!!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文通過閱讀Spring源碼,分析Bean實例化流程。 # Bean實例化入口 上一篇文章已經介紹,Bean實例化入口在AbstractApplicationContext類的finishBeanFactoryInitialization方法: ```java protected void fini ...
  • # 1、Java常用插件實現方案 ## 1.2、serviceloader方式 serviceloader是java提供的spi模式的實現。按照介面開發實現類,而後配置,java通過ServiceLoader來實現統一介面不同實現的依次調用。而java中最經典的serviceloader的使用就是J ...
  • **原文鏈接:** [Go 語言 context 都能做什麼?](https://mp.weixin.qq.com/s/7IliODEUt3JpEuzL8K_sOg) 很多 Go 項目的源碼,在讀的過程中會發現一個很常見的參數 `ctx`,而且基本都是作為函數的第一個參數。 為什麼要這麼寫呢?這個參 ...
  • POM( Project Object Model,項目對象模型 ) 是 Maven 工程的基本工作單元,它是一個 XML 文件,包含了項目的基本信息,用於描述項目如何構建,聲明項目依賴等等。執行任務或目標時,Maven 會在當前目錄中查找並讀取 POM,獲取所需的配置信息,然後執行目標。 1、基本 ...
  • # HttpServletResponse對象 ## 基本介紹 ​ Web伺服器收到客戶端的http請求,會針對每次請求,分別創建一個用於**代表請求**的 request對象 和**代表響應**的 response對象。 ​ request 和 response對象 代表請求和響應:**獲取客戶瑞 ...
  • 不知不覺,《C++面試八股文》已經更新30篇了,這是我第一次寫技術博客,由於個人能力有限,出現了不少紕漏,在此向各位讀者小伙伴們致歉。 為了不誤導更多的小伙伴,以後會不定期的出勘誤文章,請各位小伙伴留意。 在《[C++面試八股文:C++中,設計一個類要註意哪些東西?](https://zhuanla ...
  • ### 1、背景介紹 前兩天,現場的同事使用開發的程式測試時,發現日誌中報`etcdserver: mvcc: database space exceeded`,導致 etcd 無法連接。很奇怪,我們開發的程式只用到了 etcd 做程式的主備,並沒有往 etcd 中寫入大量的數據,為什麼會造成 et ...
  • # WPF複習知識點記錄 由於近幾年主要在做Web項目,客戶端的項目主要是以維護為主,感覺對於基礎知識的掌握沒有那麼牢靠,趁著這個周末重新複習下WPF的相關知識。 文章內容主要來自大佬劉鐵錳老師的經典著作《深入淺出WPF》。 因為是複習,所以知識內容不會一一記錄,如有需要瞭解更多可以看書中內容。 * ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...