.NET Core中SignalR跨本地项目消息通知实现及报错解决咨询
.NET Core SignalR跨项目通知实现及报错修复
核心问题分析
- 发送端使用了旧版SignalR API(
IHubProxy),.NET Core SignalR已弃用该接口 - 调用Hub方法时错误传入Hub名称而非目标方法名
- 同步阻塞调用
Wait()易引发死锁 - 跨域配置缺失,跨项目请求被拦截
- 前端连接初始化代码不完整
修复步骤及代码示例
1. 接收端(展示通知项目)配置
配置跨域策略
在.NET 6+的Program.cs中添加跨域规则,允许发送端的请求来源:
var builder = WebApplication.CreateBuilder(args); // 注册SignalR服务 builder.Services.AddSignalR(); // 配置跨域,替换为发送端实际URL builder.Services.AddCors(options => { options.AddPolicy("SignalRCorsPolicy", policy => { policy.WithOrigins("https://localhost:发送端端口") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); var app = builder.Build(); app.UseCors("SignalRCorsPolicy"); // 映射Hub路由 app.MapHub<ChatHub>("/chatHub"); app.Run();
接收端Hub实现
确保ChatHub包含可被调用的SendMessage方法,并将消息推送给所有客户端:
using Microsoft.AspNetCore.SignalR; public class ChatHub : Hub { public async Task SendMessage(string user, string message) { // 将消息推送给所有连接的客户端 await Clients.All.SendAsync("ReceiveMessage", user, message); } }
2. 发送端(发送通知项目)修复代码
改用.NET Core SignalR新版API,替换旧的IHubProxy写法:
using Microsoft.AspNetCore.SignalR.Client; // 在异步方法中执行,避免同步阻塞 public async Task SendNotification() { // 替换为接收端实际URL,需包含Hub路由后缀 var connection = new HubConnectionBuilder() .WithUrl("https://localhost:接收端端口/chatHub", options => { options.WithCredentials = true; }) .Build(); try { await connection.StartAsync(); // 调用接收端Hub的SendMessage方法,传入正确参数 await connection.InvokeAsync("SendMessage", "系统通知", "Hello World"); } catch (Exception ex) { Console.WriteLine($"发送失败:{ex.Message}"); } finally { await connection.DisposeAsync(); } }
3. 前端(接收端页面)完整连接代码
确保前端正确初始化SignalR连接,并监听消息事件展示通知:
<!-- 引入SignalR客户端库 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.min.js"></script> <script> // 创建连接 const connection = new signalR.HubConnectionBuilder() .withUrl("/chatHub") .withAutomaticReconnect() .build(); // 监听接收消息事件,实现通知展示逻辑 connection.on("ReceiveMessage", function (user, message) { // 示例:弹出提示或插入页面元素 alert(`${user}: ${message}`); const li = document.createElement("li"); document.getElementById("messagesList").appendChild(li); li.textContent = `${user}: ${message}`; }); // 启动连接 connection.start().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>
关键注意事项
- 确保发送端和接收端的SignalR版本一致(如统一使用6.x系列)
- 检查URL和端口号是否正确,避免拼写错误
- 跨域策略必须包含发送端的完整Origin(协议+域名+端口)
- 异步方法中禁止使用
Wait()/Result(),改用await防止死锁
内容的提问来源于stack exchange,提问作者krunal
相关产品推荐
相关产品推荐

