.NET Core中WebSocket下如何向SignalR Hub传递当前页面URL
问题解答
1. SignalR使用WebSocket传输时能否传递自定义头?
不能。WebSocket协议的握手阶段基于HTTP,但SignalR在使用WebSocket传输时,不会将自定义HTTP头传递到服务器端。这就是你通过headers配置的Page-Url在WebSocket模式下无法被服务器获取,而HTTP长轮询等其他传输方式可以正常获取的原因。
2. 传递自定义数据的替代方案
方案一:将数据附加到连接URL的查询参数中
这是最简单直接的方式,客户端在构建连接URL时把页面URL作为查询参数带上,服务器从HttpContext的查询集合中获取。
客户端代码(Angular):
const pageUrl = encodeURIComponent(window.location.href); this.hubConnection = new signalR.HubConnectionBuilder() .withUrl(`${apiUrl}sharedconnectionhub?pageUrl=${pageUrl}`, { accessTokenFactory: () => accessToken, transport: signalR.HttpTransportType.WebSockets }) .withAutomaticReconnect() .build();
服务端代码(.NET Core):
public class MyHub : Hub { public override async Task OnConnectedAsync() { var httpContext = Context.GetHttpContext(); if (httpContext != null) { if (httpContext.Request.Query.TryGetValue("pageUrl", out var pageUrl)) { var decodedUrl = Uri.UnescapeDataString(pageUrl); Console.WriteLine($"Page URL: {decodedUrl}"); } } await base.OnConnectedAsync(); } }
方案二:连接建立后主动调用Hub方法传递数据
在SignalR连接成功建立后,客户端主动调用服务器端的Hub方法,将页面URL等自定义数据发送过去。这种方式更灵活,适合需要传递较多数据的场景。
客户端代码(Angular):
this.hubConnection.start().then(() => { // 连接成功后调用服务器方法传递页面URL this.hubConnection.invoke('SendPageUrl', window.location.href) .catch(err => console.error(err)); }).catch(err => console.error(err));
服务端代码(.NET Core):
public class MyHub : Hub { public override async Task OnConnectedAsync() { await base.OnConnectedAsync(); } // 定义接收页面URL的方法 public Task SendPageUrl(string pageUrl) { Console.WriteLine($"Page URL: {pageUrl}"); // 可将URL与当前连接ID关联存储,供后续业务使用 return Task.CompletedTask; } }
方案三:使用JWT令牌携带自定义声明(若使用Token认证)
如果项目使用JWT作为访问令牌,可在令牌中添加自定义声明来携带页面URL,服务器端通过解析令牌获取数据。这种方式适合需要和身份认证绑定的场景。
客户端代码(Angular):
// 假设Token生成时已将pageUrl作为自定义声明添加 this.hubConnection = new signalR.HubConnectionBuilder() .withUrl(`${apiUrl}sharedconnectionhub`, { accessTokenFactory: () => accessToken, // 令牌包含pageUrl声明 transport: signalR.HttpTransportType.WebSockets }) .withAutomaticReconnect() .build();
服务端代码(.NET Core):
using System.Security.Claims; public class MyHub : Hub { public override async Task OnConnectedAsync() { var user = Context.User; if (user != null) { var pageUrlClaim = user.FindFirst("Page-Url"); if (pageUrlClaim != null) { Console.WriteLine($"Page URL: {pageUrlClaim.Value}"); } } await base.OnConnectedAsync(); } }
内容的提问来源于stack exchange,提问作者Kristijan Nikoloski
相关产品推荐
相关产品推荐

