You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET控制器中触发SignalR前端的connection.on方法?

问题分析与解决方案

核心错误:Hub路由映射不匹配

你的Startup类中,将/DatabaseHub路由映射到了SignalHub而非DatabaseHub,导致前端连接的Hub与后端处理消息的Hub不一致,消息无法传递到前端。

修复步骤:

  1. 修正Hub路由映射
    在Startup的Configure方法中,修改UseEndpoints里的Hub映射:
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=index}/{id?}");
    endpoints.MapRazorPages();
    endpoints.MapHub<SignalHub>("/SignalHub");
    // 把下面这行的SignalHub改成DatabaseHub
    endpoints.MapHub<DatabaseHub>("/DatabaseHub");
});
  1. 移除不必要的Hub单例注册
    在Startup的ConfigureServices中,删除services.AddSingleton<DatabaseHub>();。SignalR会自动管理Hub实例的生命周期,手动注册单例会引发上下文异常。

  2. 重构数据库监听逻辑到托管服务
    你当前在控制器的Account方法中创建SqlDependencyEx监听,每次请求该方法都会新建一个监听实例,不仅重复监听还可能因控制器释放导致监听失效。将监听逻辑移到托管服务中:

创建托管服务类:

using SqlDependencyEx;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;

namespace Flubr
{
    public class DatabaseChangeListenerService : IHostedService, IDisposable
    {
        private readonly IHubContext<DatabaseHub> _hubContext;
        private SqlDependencyEx _listener;

        public DatabaseChangeListenerService(IHubContext<DatabaseHub> hubContext)
        {
            _hubContext = hubContext;
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            var connectionString = "Server=(local)\\sqlexpress;Database=Flubr;Trusted_Connection=True;MultipleActiveResultSets=true";
            _listener = new SqlDependencyEx(connectionString, "Flubr", "UserMessage");
            
            _listener.TableChanged += async (sender, args) =>
            {
                await _hubContext.Clients.All.SendAsync("DatabaseChanged", "数据库已变更");
                Console.WriteLine("数据库已变更");
            };
            
            _listener.Start();
            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _listener?.Stop();
            return Task.CompletedTask;
        }

        public void Dispose()
        {
            _listener?.Dispose();
        }
    }
}

然后在Startup的ConfigureServices中注册该服务:

services.AddHostedService<DatabaseChangeListenerService>();
  1. 简化控制器逻辑
    删除Account方法中的监听代码,保留测试用的消息发送(可选):
public async Task<IActionResult> Account(string id)
{
    // 测试:确认HubContext可正常发送消息
    await _hubContext.Clients.All.SendAsync("DatabaseChanged", "Account方法已触发");
    ViewBag.change = "hey";
    return View();
}

验证步骤:

  1. 重启应用,打开浏览器控制台,查看SignalR连接是否成功(无404或连接错误)。
  2. 触发数据库变更,检查前端是否弹出通知,同时查看后端控制台的输出。

内容的提问来源于stack exchange,提问作者roger blinkins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 17:12:54