如何从Hub外部向Blazor SignalR聊天插入消息?
解决Blazor SignalR从Hub外部插入消息的方案
一、C#端直接通过HubContext发送机器人消息
不需要经过前端输入框,后端可直接借助IHubContext向客户端推送消息,适合机器人主动发送回复的场景。
1. 创建消息推送服务
public class ChatBotService { private readonly IHubContext<ChatHub> _hubContext; public ChatBotService(IHubContext<ChatHub> hubContext) { _hubContext = hubContext; } // 发送消息到指定用户 public async Task SendBotMessageToUser(string userId, string message) { await _hubContext.Clients.User(userId).SendAsync("ReceiveMessage", "ChatBot", message); } // 发送消息到所有在线用户 public async Task SendBotMessageToAll(string message) { await _hubContext.Clients.All.SendAsync("ReceiveMessage", "ChatBot", message); } }
2. 注册服务
在Program.cs中注入该服务:
builder.Services.AddScoped<ChatBotService>();
3. 调用服务发送消息
在任意后端逻辑(如API控制器、其他业务服务)中注入ChatBotService即可调用:
public class SomeController : ControllerBase { private readonly ChatBotService _chatBotService; public SomeController(ChatBotService chatBotService) { _chatBotService = chatBotService; } [HttpGet] public async Task<IActionResult> TriggerBotReply(string userId) { await _chatBotService.SendBotMessageToUser(userId, "这是机器人的自动回复"); return Ok(); } }
二、前端处理点击链接发送预定义消息
针对机器人消息中的链接,通过Blazor组件自身方法处理,避免JS直接操作DOM导致的双向绑定失效问题。
1. Blazor组件核心代码
<div id="chatComponent"> <input @bind="_messageInput" placeholder="输入消息..." /> <button @onclick="SendMessage">发送</button> <div class="chat-messages"> @foreach (var msg in _chatMessages) { <div> <strong>@msg.User:</strong> @if (msg.IsBotLink) { <a @onclick="() => SendPredefinedMessage(msg.PredefinedText)">@msg.DisplayContent</a> } else { @msg.DisplayContent } </div> } </div> </div> @code { private string _messageInput; private HubConnection _hubConnection; private List<ChatMessage> _chatMessages = new(); protected override async Task OnInitializedAsync() { _hubConnection = new HubConnectionBuilder() .WithUrl(NavigationManager.ToAbsoluteUri("/chatHub")) .Build(); _hubConnection.On<string, string>("ReceiveMessage", (user, message) => { // 解析机器人消息(示例:判断是否包含链接) var isBotLink = message.Contains("[链接]"); var chatMsg = new ChatMessage { User = user, DisplayContent = isBotLink ? "点击查看详情" : message, IsBotLink = isBotLink, PredefinedText = isBotLink ? "这是预定义的回复内容" : null }; _chatMessages.Add(chatMsg); StateHasChanged(); }); await _hubConnection.StartAsync(); } private async Task SendMessage() { if (!string.IsNullOrEmpty(_messageInput) && _hubConnection.State == HubConnectionState.Connected) { await _hubConnection.SendAsync("SendMessage", "当前用户", _messageInput); _messageInput = string.Empty; } } // 处理预定义消息发送 private async Task SendPredefinedMessage(string predefinedText) { _messageInput = predefinedText; await SendMessage(); } private class ChatMessage { public string User { get; set; } public string DisplayContent { get; set; } public bool IsBotLink { get; set; } public string PredefinedText { get; set; } } }
2. 可选:JS调用Blazor组件方法
如果必须通过JS触发(如第三方渲染的消息内容),可通过DotNet.invokeMethodAsync调用组件的公开方法:
Blazor组件添加可调用方法
[JSInvokable] public async Task SendPredefinedMessageFromJS(string predefinedText) { _messageInput = predefinedText; await SendMessage(); }
JS代码触发调用
function triggerPredefinedMessage(message) { DotNet.invokeMethodAsync('你的项目程序集名称', 'SendPredefinedMessageFromJS', message); }
在消息的HTML链接中使用:
<a href="javascript:void(0);" onclick="triggerPredefinedMessage('预定义消息内容')">点击发送预定义消息</a>
内容的提问来源于stack exchange,提问作者Daniel Schneider
相关产品推荐
相关产品推荐

