SignalR Self Host+MVC等多端消息推送服务(一)

“SignalR Self Host+MVC等多端消息推送服务(一)”是一篇介绍使用SignalR实现消息推送服务的教程。它包括了从安装SignalR到在MVC网站上实现消息推送的完整过程。

以下是该教程的详细攻略:

第一步:安装SignalR

在开始之前,我们应该下载并安装SignalR,可以通过NuGet包管理器来安装。使用以下命令来安装:

Install-Package Microsoft.AspNet.SignalR

第二步:创建SignalR Hub类

创建一个Hub类,用于将消息从服务器推送到客户端。可以为此使用Visual Studio的“添加新项”对话框,选择“SignalR Hub Class”模板。例如,如果我们要创建一个名为“ChatHub”的类,可以使用以下代码:

using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;

namespace SignalRChat
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

在上面的代码中,我们创建了一个名为“SendMessage”的方法,该方法将消息发送到所有连接的客户端。我们还在方法的签名中使用了async和await关键字,以便异步发送广播。

需要注意的是,在SignalR中,方法名称用于标识客户端应调用的方法名称。在上面的代码中,我们使用了“ReceiveMessage”作为客户端应调用的方法名称。

第三步:配置SignalR

要配置SignalR,需要将其添加到Web应用程序的Startup.cs文件中。在ConfigureServices方法中添加以下代码:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSignalR();
}

接下来,在Configure方法中,添加以下代码:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/chatHub");
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

在上面的代码中,我们首先使用app.UseRouting()将路由服务添加到管道中,然后使用app.UseEndpoints()将SignalR的终结点和MVC的默认控制器路由添加到管道中。

第四步:调用客户端方法

要从服务器端调用客户端方法,可以在Hub类中包含一个方法,该方法将指定的消息发送到 connected clients。例如,如果我们要使用JavaScript从客户端调用“ReceiveMessage”方法,可以执行以下操作:

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

connection.on("ReceiveMessage", function (user, message) {
    console.log(user + " says " + message);
});

connection.start().then(function () {
    connection.invoke("SendMessage", "Alice", "Hello");
}).catch(function (err) {
    return console.error(err.toString());
});

在上面的代码中,我们首先使用signalR.HubConnectionBuilder()创建连接对象,然后在调用connection.on()方法时,将“ReceiveMessage”方法注册为客户端应接收的方法。最后,我们通过调用connection.invoke()方法来调用服务器上的“SendMessage”方法。在服务器上调用此方法后,客户端上注册的“ReceiveMessage”方法将被调用。

示例说明

示例1:群聊

下面是示例1的完整代码:

using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;

namespace SignalRChat
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}
<!-- Views/Home/Index.cshtml -->
@{
    ViewData["Title"] = "Chat Room";
}
<h2>Chat Room</h2>
<input type="text" id="userInput" placeholder="user" />
<input type="text" id="messageInput" placeholder="message" />
<button id="sendButton">Send</button>
<div id="messages">
</div>
@section Scripts
{
    <script src="~/lib/signalr/dist/browser/signalr.js"></script>
    <script>
        var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

        connection.on("ReceiveMessage", function (user, message) {
            var encodedMsg = user + " says " + message;
            var li = document.createElement("li");
            li.textContent = encodedMsg;
            document.getElementById("messages").appendChild(li);
        });

        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();
        });

        connection.start().catch(function (err) {
            return console.error(err.toString());
        });
    </script>
}

在该示例中,我们实现一个简单的聊天室,允许用户输入其名称和消息,然后将消息广播到所有其他连接的客户端。用户在客户端输入名称和消息后,单击“发送”按钮。 将从客户端发送到服务器的消息称为“user”和“message”。 服务器会将此消息发送到所有连接的客户端,并更新消息列表。在客户端上,我们使用connection.invoke()方法调用服务器上的SendMessage方法,并使用on()方法订阅“ReceiveMessage”事件以接收广播消息。

示例2:实时显示股票价格

下面是示例2的完整代码:

using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;

namespace SignalRStockTicker
{
    public class StockTicker
    {
        // Singleton instance
        private readonly static Lazy<StockTicker> _instance = new(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));

        private readonly object _stockPricesLock = new();
        private readonly Random _updateOrNotRandom = new();
        private readonly Dictionary<string, Stock> _stocks = new();
        private readonly Timer _timer;
        private StockTicker(IHubConnectionContext<dynamic> clients)
        {
            Clients = clients;

            _stocks = GenerateStocks();

            _timer = new Timer
            {
                Interval = 2000
            };

            _timer.Elapsed += UpdateStockPrices;
        }

        private void UpdateStockPrices(object sender, ElapsedEventArgs e)
        {
            foreach (var stock in _stocks.Values)
            {
                if (_updateOrNotRandom.NextDouble() > 0.1)
                {
                    // In real life we'd query a database or other data source to get new stock prices.
                    // Here we'll just manipulate the existing data to make it look like a stock market.
                    var pos = _updateOrNotRandom.NextDouble() < 0.5 ? 1 : -1;
                    var change = _updateOrNotRandom.NextDouble() * 2.0;  //stock price between -2% and +2%
                    stock.Price += pos * change * stock.Price;
                    stock.Price = Math.Round(stock.Price, 2);

                    // This optional logic makes sure that the price change is no more than 10 percent.
                    var percentageChange = change * 100 / stock.Price;
                    if (Math.Abs(percentageChange) > 10)
                    {
                        stock.Price -= pos * change * stock.Price;
                        stock.Price = Math.Round(stock.Price, 2);
                    }

                    // Send the new stock price to all clients.
                    Clients.All.updateStockPrice(stock);
                }
            }
        }

        public static StockTicker Instance => _instance.Value;
        private IHubConnectionContext<dynamic> Clients { get; set; }

        public IEnumerable<Stock> GetAllStocks()
        {
            return _stocks.Values;
        }

        private Dictionary<string, Stock> GenerateStocks()
        {
            return new Dictionary<string, Stock>
            {
                { "MSFT", new Stock { Symbol = "MSFT", Price = 200.1m } },
                { "AAPL", new Stock { Symbol = "AAPL", Price = 400.2m } },
                { "GOOG", new Stock { Symbol = "GOOG", Price = 600.3m } },
                { "AMZN", new Stock { Symbol = "AMZN", Price = 800.4m } },
                { "FB", new Stock { Symbol = "FB", Price = 50.5m } }
            };
        }

        public void Start()
        {
            _timer.Start();
        }

        public void Stop()
        {
            _timer.Stop();
        }

        public Stock GetStock(string symbol)
        {
            var stock = new Stock { Symbol = "NOT FOUND", Price = 0m };

            if (_stocks.ContainsKey(symbol))
            {
                stock = _stocks[symbol];
            }

            return stock;
        }
    }

    public class Stock
    {
        public string Symbol { get; set; }
        public decimal Price { get; set; }
    }
}
using Microsoft.AspNet.SignalR;

namespace SignalRStockTicker
{
    public class StockTickerHub : Hub
    {
        private readonly StockTicker _stockTicker;

        public StockTickerHub() : this(StockTicker.Instance) { }

        public StockTickerHub(StockTicker stockTicker)
        {
            _stockTicker = stockTicker;
        }

        public void GetAllStocks()
        {
            var stocks = _stockTicker.GetAllStocks();
            Clients.Caller.updateAllStocks(stocks);
        }

        public void GetStock(string symbol)
        {
            var stock = _stockTicker.GetStock(symbol);
            Clients.Caller.updateStockPrice(stock);
        }
    }
}
<!-- Views/Home/Index.cshtml -->
@{
    ViewData["Title"] = "Stock Ticker";
}
<h2>Stock Ticker</h2>
<div id="stocks-list">
</div>
<div id="stock-price">
</div>
@section Scripts
{
    <script src="~/lib/signalr/dist/browser/signalr.js"></script>
    <script>
        var connection = new signalR.HubConnectionBuilder().withUrl("/stockTickerHub").build();

        connection.on("updateAllStocks", function (stocks) {
            var table = document.createElement("table");
            for (stock of stocks) {
                var row = document.createElement("tr");
                var symbolCell = document.createElement("td");
                var priceCell = document.createElement("td");
                symbolCell.textContent = stock.symbol;
                priceCell.textContent = stock.price;
                row.appendChild(symbolCell);
                row.appendChild(priceCell);
                table.appendChild(row);
            }
            document.getElementById("stocks-list").appendChild(table);
        });

        connection.on("updateStockPrice", function (stock) {
            // Update the stock price.
            document.getElementById("stock-price").textContent =
                stock.symbol + ": " + stock.price;
        });

        connection.start().then(function () {
            connection.invoke("GetAllStocks").catch(function (err) {
                return console.error(err.toString());
            });
        });

        setInterval(function () {
            var symbols = ['MSFT', 'AAPL', 'GOOG', 'AMZN', 'FB'];
            var symbol = symbols[Math.floor(Math.random() * symbols.length)];
            connection.invoke("GetStock", symbol).catch(function (err) {
                return console.error(err.toString());
            });
        }, 1000);
    </script>
}

在此示例中,我们使用StockTicker类和StockTickerHub类创建了一个简单的股票行情跟踪器。其中StockTicker是一个单例,用于在一定时间间隔内更新所有股票价格的模拟数据,并将更新后的股票价格发送给所有连接的客户端。StockTickerHub则包含两个方法,分别用于获取所有股票价格和特定股票的价格,并使用Clients对象将数据发送到客户端。

在客户端上,我们使用connection.on()方法订阅“updateAllStocks”和“updateStockPrice”事件。当连接成功时,我们通过connection.invoke()方法调用服务器上的GetAllStocks方法,以获取所有股票价格。我们还使用javascript中的setInterval()函数,每秒调用服务器上的GetStock方法,随机地请求一个股票的价格,并实时更新股票价格。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SignalR Self Host+MVC等多端消息推送服务(一) - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 详解C++ string常用截取字符串方法

    详解C++ string常用截取字符串方法 在C++中,string类型是一个非常常用的数据类型,它可以存储字符串并提供一系列字符串处理的方法。其中,截取字符串是string的常见操作之一。下面是C++ string常用的截取字符串方法: 方法一:使用substr函数 substr函数可以截取字符串中的任意一段子串,其参数为子串截取的开始位置和长度,其函数原…

    other 2023年6月20日
    00
  • Win10右键菜单添加PowerShell脚本新建项图文步骤

    下面是Win10右键菜单添加PowerShell脚本新建项的完整攻略。 步骤一:创建PowerShell脚本文件 首先,需要创建一个PowerShell脚本文件,用于在右键菜单中添加新建项时调用。创建方法有以下两种示例: 示例一:使用Notepad++ 右键点击桌面或任意空白处,选择“新建”->“文本文档”,命名为“New_PowerShell_Scr…

    other 2023年6月27日
    00
  • Go中变量命名规则与实例

    Go中变量命名规则与实例攻略 在Go语言中,变量的命名规则是非常重要的,它能够提高代码的可读性和可维护性。下面是Go中变量命名的一些规则和示例说明: 1. 变量命名规则 变量名由字母、数字和下划线组成。 变量名必须以字母或下划线开头。 变量名区分大小写。 避免使用Go语言的关键字作为变量名。 2. 示例说明 示例1:基本变量命名 package main i…

    other 2023年8月8日
    00
  • 浅析Vue 生命周期

    浅析Vue生命周期 Vue生命周期可以分为8个阶段,分别是: 创建阶段:beforeCreate、created、beforeMount; 挂载阶段:mounted; 更新阶段:beforeUpdate、updated; 销毁阶段:beforeDestroy、destroyed。 这些钩子函数可以让你在特定的时刻执行到某些自定义的逻辑,比如数据的初始化、渲染…

    other 2023年6月27日
    00
  • Android编程之基于Log演示一个activity生命周期实例详解

    让我来向你详细讲解一下“Android编程之基于Log演示一个activity生命周期实例详解”的完整攻略。 什么是Android中的生命周期? 在Android应用程序中,Activity生命周期指的是从Activity的创建(或从新创建)到销毁的整个过程。整个过程包括了Activity的启动、暂停、停止甚至是销毁等一系列的生命周期事件。在每个生命周期事件…

    other 2023年6月27日
    00
  • PPT怎么利用触发器实现简单交互动画?

    下面是关于“PPT怎么利用触发器实现简单交互动画?”的完整攻略。 什么是触发器 在PPT中,触发器是一种可以触发特殊效果的工具,可以让幻灯片更生动、有趣。在PPT中,触发器可以让元素随着鼠标或其他用户操作而发生动画效果。触发器有各种各样的类型,比如按钮、文本框、图片等,可以实现不同的动画效果。 如何利用触发器实现简单交互动画 利用触发器实现简单交互动画的步骤…

    other 2023年6月27日
    00
  • thinkphp5.1框架模板布局与模板继承用法分析

    ThinkPHP5.1框架模板布局与模板继承用法分析攻略 1. 概述 ThinkPHP5.1是一款流行的PHP开发框架,它提供了强大的模板引擎功能,其中包括模板布局和模板继承。模板布局允许我们定义一个公共的页面布局,而模板继承则允许我们在不同的页面中继承这个布局,并进行相应的扩展和修改。 2. 模板布局 模板布局允许我们定义一个公共的页面布局,这样我们就可以…

    other 2023年8月23日
    00
  • 使用vue-cli搭建SPA项目的详细过程

    使用vue-cli搭建SPA项目的详细过程 1. 安装Node.js和npm 在开始之前,确保你已经安装了Node.js和npm。你可以在官方网站上下载并安装最新版本的Node.js。 2. 安装vue-cli 打开终端或命令提示符,运行以下命令来全局安装vue-cli: npm install -g @vue/cli 3. 创建新的Vue项目 在终端或命令…

    other 2023年7月28日
    00
合作推广
合作推广
分享本页
返回顶部