一、在 ASP.NET Core 中使用 SignalR


一、介紹

SignalR 是一個用於實現實時網站的 Microsoft .NET 庫。它使用多種技術來實現服務器與客戶端間的雙向通信,服務器可以隨時將消息推送到連接的客戶端。

https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?tabs=visual-studio&view=aspnetcore-3.0

 

 

二、新建Core MVC項目並安裝

三、添加 SignalR 客戶端庫

在“解決方案資源管理器” 中,右鍵單擊項目,然后選擇“添加” >“客戶端庫” 

在“添加客戶端庫” 對話框中,對於“提供程序” ,選擇“unpkg” 。

對於“庫” ,輸入 @aspnet/signalr@1,然后選擇不是預覽版的最新版本。

選擇“選擇特定文件” ,展開“dist/browser” 文件夾,然后選擇“signalr.js” 和“signalr.min.js” 。

將“目標位置” 設置為 wwwroot/lib/signalr/ ,然后選擇“安裝” 。

 

 

 

 四、創建 SignalR 中心即操作中心。

Hub 消息處理中心

public class TestHub : Hub
{
    public TestHub()
    {
    }

    public async Task SendMessage(string message, string name)
    {
        #region Client
        //this.Context.ConnectionId                 //每個連接一個connectionId  表示唯一客戶端
        //this.Clients.Client().SendAsync();        //指定發送消息
        //this.Clients.Clients()        
        #endregion             //給多個client發消息


        #region Group
        //this.Clients.Group();                     //給某個組發消息
        //this.Clients.Groups()                     //給多個組發消息
        //this.Groups.AddToGroupAsync()             //將指定連接加入組
        //this.Groups.RemoveFromGroupAsync()        //將指定連接移除組 
        #endregion

        await Clients.All.SendAsync("onMsg", DateTime.Now, message);
    }


    //上下線消息  連接、斷開事件

    //客戶端連接上
    public override Task OnConnectedAsync()
    {
        return base.OnConnectedAsync();
    }

    //客戶端斷開
    public override Task OnDisconnectedAsync(Exception exception)
    {
        string connectionId = this.Context.ConnectionId;
        return base.OnDisconnectedAsync(exception);
    }
}

以上可以看到SignalR封裝了很多常用方法(發送指定消息、群發...),我們可以很簡單的使用達到目的

創建 Hubs 文件夾 。

在 Hubs 文件夾中,使用以下代碼創建 ChatHub.cs 文件 :

 

using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Ban.Hubs
{
    public class ChatHub:Hub 
    {
        /// <summary>
        /// /服務端方法 發送消息--發送給所有連接的客戶端
        /// </summary>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessage(string user,string message)
        {
            //ReceiveMessage 為客戶端方法,讓所有客戶端調用這個方法
            await Clients.All.SendAsync("ReceiveMessage",user,message);
        }

        /// <summary>
        /// 客戶端連接的時候調用
        /// </summary>
        /// <returns></returns>
        public override Task OnConnectedAsync()
        {
            Trace.WriteLine("客戶端連接成功");
            return base.OnConnectedAsync();
        }//所有鏈接的客戶端都會在這里

        /// <summary>
        /// 連接終止時調用。
        /// </summary>
        /// <returns></returns>
        public override Task OnDisconnectedAsync(Exception exception)
        {
            Trace.WriteLine("連接終止");
            return base.OnDisconnectedAsync(exception);
        }
       
    }
}

六、配置 SignalR

必須配置 SignalR 服務器,以將 SignalR 請求傳遞到 SignalR。

startupConfigureServices方法內部添加SignalR服務services.AddSignalR();Configure中配置具體的Hub(路由器、中轉):

    app.UseSignalR(routes =>
    {
        routes.MapHub<TestHub>("/testHub");     //可以多個map
    });
    
    app.UseMvc();           //注意UseSignalR需要在UseMvc()之前

這樣SignalR服務器端就開發完成了,網頁、Java、.Net客戶端都可以連接的

 

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using test.Hubs; //3、引用 處理客戶端 - 服務器通信的高級管道
namespace test
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddSignalR();//1、添加服務
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseSignalR(routes => //2、引用
            {
                routes.MapHub<ChatHub>("/chatHub");
            });
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

 

 七、添加 SignalR 客戶端代碼(創建index控制器和視圖)

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div class="container">
        <div class="row">&nbsp;</div>
        <div class="row">
            <div class="col-6">&nbsp;</div>
            <div class="col-6">
                User..........<input type="text" id="userInput" />
                <br />
                Message...<input type="text" id="messageInput" />
                <input type="button" id="sendButton" value="Send Message" />
            </div>
        </div>
        <div class="row">
            <div class="col-12">
                <hr />
            </div>
        </div>
        <div class="row">
            <div class="col-6">&nbsp;</div>
            <div class="col-6">
                <ul id="messagesList"></ul>
            </div>
        </div>
    </div>
    <script src="~/lib/signalr/dist/browser/signalr.js"></script>
    <script type="text/javascript">
        "use strict";
        var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
        //在建立連接之前禁用發送按鈕
        document.getElementById("sendButton").disabled = true;
        //接受消息
        connection.on("ReceiveMessage", function (user, message) {
            var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
            var encodedMsg = user + " says " + msg;
            var li = document.createElement("li");
            li.textContent = encodedMsg;
            document.getElementById("messagesList").appendChild(li);
        });
        //開始鏈接
        connection.start().then(function () {
            document.getElementById("sendButton").disabled = false;
        }).catch(function (err) {
            return console.error(err.toString());
        });
        //發送消息
        document.getElementById("sendButton").addEventListener("click", function (event) {
            var user = document.getElementById("userInput").value;
            var message = document.getElementById("messageInput").value;
            connection.invoke("SendMessage", user, message).catch(function (err) {
                return console.error(err.toString());
            });
            event.preventDefault();
        });
    </script>
</body>
</html>

 

 

 

 

 

 

Controller中調用SignalR服務

在構造函數注入IHubContext<>就可以直接使用了,非常方便:

   private readonly IHubContext<TestHub> _hubContext;

    public HomeController(IHubContext<TestHub> hubContext)
    {
        _hubContext = hubContext;
    }
    
    public async Task<IActionResult> Notify()
    {
        //拿不到當前Hub的clientId  線程是唯一的
        await _hubContext.Clients.All.SendAsync("onMsg", "from controller msg");
        return Ok();
    }

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM