我试图使用SignalR(.NET 6)和Angular ~13实现直接消息到特定用户,到目前为止,我得到了很多关于实现的信息,但没有一个工作。
所以在客户端(Angular)我有方法发送消息
export interface IChatMessage {
id?: number;
message: string;
from?: string;
to?: string;
created?: Date | null;
}
字符串
其中发送到hub我只发送message
和to
,to
是该消息的接收者。我的chat.service.ts
是
export class ChatService {
private hubConnection: HubConnection;
private receivedMessageSubject = new Subject<IChatMessage>();
public connectionId: string;
receivedMessage$: Observable<IChatMessage> = this.receivedMessageSubject.asObservable();
constructor(private apiService: ApiService) {
this.hubConnection = new HubConnectionBuilder()
.withUrl(environment.apiUrl + API_ROUTES.CHAT, {accessTokenFactory: () => localStorage.getItem('token')})
.build();
this.hubConnection.start().then(() => console.log('connection started')).then(() => this.getConnectionId()).catch((err) => console.error(err));
this.hubConnection.on('ReceiveMessage', (message) => {
console.log('Received message from server:', message);
this.receivedMessageSubject.next(message);
});
}
private getConnectionId = () => {
this.hubConnection.invoke('getconnectionid')
.then((data) => {
this.connectionId = data;
});
}
getMessages(id: string) {
return this.apiService.post(environment.apiUrl + API_ROUTES.CHAT_MESSAGES, {userId: id});
}
sendMessage(message: IChatMessage): void {
this.hubConnection.invoke('SendMessage', message, this.connectionId)
.then((response) => console.log('Server response:', response))
.catch(error => console.error('Error sending message through SignalR:', error));
}
}
型
在服务器端,我有集线器ChatHub
public async Task SendMessage(ChatMessage message, string connectionId)
{
try
{
var headers = Context.GetHttpContext().Request.Headers;
var user = Context.GetHttpContext().User.Identity;
Console.WriteLine(JsonSerializer.Serialize(Context.ConnectionId));
await Clients.User(connectionId).SendAsync("ReceiveMessage", message);
}
catch (Exception ex)
{
Console.WriteLine($"Error in SendMessage: {ex.Message}");
throw;
}
}
型
我得到了connectionId
,但它对每个用户都是不同的,不能Map它来连接发送者和接收者。
using IUserIdProvider = Microsoft.AspNetCore.SignalR.IUserIdProvider;
...
builder.Services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
builder.Services.AddSignalR();
var app = builder.Build();
...
app.UseAuthentication();
...
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/api/chat");
endpoints.MapControllers();
});
型
还有CustomUserIdProvider : IUserIdProvider
public class CustomUserIdProvider : IUserIdProvider
{
public string GetUserId(HubConnectionContext connection)
{
var uniqueId = connection.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
return uniqueId;
}
}
型
但是CustomUserIdProvider
中的uniqueId
是空的。对于所有控制器,我有var user = _userClaims.GetUserId();
,它从User
实体的令牌中获取uniqueId
,该实体是string
并且是唯一的。它可以工作。如果我做await Clients.All.SendAsync("ReceiveMessage", message);
,它会向所有用户发送消息,'connectionId'是可用的,但只有发送方,所以接收方不会收到此消息。我不知道如何在.NET 6 +中实现这一点Angular 13,因为就像我说的,我已经尝试了过去5天基本上一切都可以在互联网上,但仍然没有运气。有没有人有任何想法如何实现这一点,所以它可以在1对1的方式发送使用接收方的uniqueId标识符?
2条答案
按热度按时间mutmk8jj1#
终于解决了这个问题。
在
Program.cs
中在AddAuthentication
中在AddJwtBearer
中(因为身份验证是使用JWT),我添加了字符串
下一个添加
builder.Services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
,在Useauthorization
之后添加型
我还创建了
CustomUserIdPrvider
型
和
SendMessage in
聊天中心`型
因此,使用
Clients.Users(message.To, user)
,我可以使用uniqueId(NOT!connectionId!)将消息内容发送给特定用户jhiyze9q2#
当用户(
browser
或other devices
)连接到Hub端点时,生成的connectionId
是由signalr
本身随机生成的,如果应用程序停止/崩溃,connectionIds
将消失,我们不能再使用它。一个用户只有一个uniqueId,但是他可以打开很多网页,可以和同事一起使用多个移动的设备,所以我们需要自己维护他们之间的关系,更多细节,you can check my answer in this thread。
这是我用于测试的样品。
字符串