SignalR angular 在获取字典对象时断开连接
SignalR angular gets disconnected while getting a dictionary object
使用 asp.net 核心 2.2 和 angular 7,(asp.net核心:signalr 1.1.0 + angular:"@aspnet/signalr": " ^1.1.4")
在我尝试将字典发送到 angular 之前,它工作正常。当它尝试发送字典时断开连接。
Utils.js:209 [2019-12-29T11:09:11.959Z] Information: WebSocket connected to ws://localhost:64408/chat?id=6d-C7eu1X-Pv8t4-RwdbYg.
Utils.js:209 [2019-12-29T11:09:12.132Z] Information: Connection disconnected.
这些是我的代码:
InMemoryChatRoomServiceclass:
public class InMemoryChatRoomService : IChatRoomService
{
private readonly Dictionary<Guid, ChatRoom> _roomInfo = new Dictionary<Guid, ChatRoom>();
public Task<IReadOnlyDictionary<Guid, ChatRoom>> GetAllRooms()
{
return Task.FromResult(_roomInfo as IReadOnlyDictionary<Guid, ChatRoom>);
}
}
IChatroomService:
using SignalR.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SignalR
{
public interface IChatRoomService
{
Task<IReadOnlyDictionary<Guid, ChatRoom>> GetAllRooms();
}
}
ChatHub class:
using Microsoft.AspNetCore.SignalR;
using SignalR.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SignalR
{
public class ChatHub : Hub
{
private readonly IChatRoomService _chatRoomService;
public ChatHub(IChatRoomService ChatRoomService)
{
_chatRoomService = ChatRoomService;
}
public override async Task OnConnectedAsync()
{
await Clients.Caller.SendAsync("ActiveRooms", await _chatRoomService.GetAllRooms());
await base.OnConnectedAsync();
}
}
}
angular:
import { Component, OnInit } from '@angular/core';
import * as signalR from "@aspnet/signalr";
import { HttpClient } from "@angular/common/http";
import { MessagePacket } from './MessagePacket.model';
import { ChatService } from './chat.service';
import { ChatRoom } from './ChatRoom.model';
@Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.scss']
})
export class ChatComponent implements OnInit {
constructor(private http: HttpClient, private chatService: ChatService) { }
private hub: signalR.HubConnection;
rooms = [ ];
messagePackets: MessagePacket[] = [];
isConnected = false;
connectionAttempts = 0;
ipAddress = '';
typedMessage = '';
userChatName = 'salar';//todo: load user data
ngOnInit() {
//build connection
this.hub = new signalR.HubConnectionBuilder()
.withUrl('http://localhost:64408/chat')
.build();
//start connection
this.startConnection();
this.hub.on('ActiveRooms', (rooms ) => {
this.ActiveRooms(rooms)
});
//on disconnect
this.hub.onclose(h => {
this.isConnected = false;
setTimeout(x => this.startConnection(), 3000)
});
}
startConnection() {
this.connectionAttempts++;
console.log('Connecting!')
this.hub
.start()
.then(() => {
this.connectionAttempts = 0;
this.isConnected = true;
console.log('Connection started!');
console.log('Getting all rooms');
// this.hub.invoke("ActiveRooms");
})
.catch(err => {
if (this.connectionAttempts < 10) {
console.log(this.connectionAttempts + ' try for connection')
setTimeout(x => this.startConnection(), 3000)
} else {
console.log('Error while establishing connection. changed mode to manual')
}
});
}
ActiveRooms(rooms ) {
var x = '';
// this.rooms = rooms;
}
}
当我跟踪时,它会尝试发回字典,之后,信号器会断开连接并尝试再次连接。如果它不是字典而是像字符串或其他对象,它工作正常。
更新:
当我将字典的类型 GUID 更改为 STRING 时,一切正常:
public Task<IReadOnlyDictionary<string, ChatRoom>> GetAllRooms()
{
//type guid gives error so needs to be converted to string
Dictionary<string, ChatRoom> result = new Dictionary<string, ChatRoom>();
foreach (var room in _roomInfo)
{
result.Add(room.Key.ToString(), room.Value);
}
return Task.FromResult(result as IReadOnlyDictionary<string, ChatRoom>);
}
GUID 有问题。
SignalR 在想要 serialize/deserialize GUID 时遇到问题,并且它必须在 C# 端和 JS 端工作。 GUID 有点棘手。它是一个结构,而不是 class。它有二进制表示和字符串表示。
我发现了这个问题:
https://github.com/aspnet/SignalR/issues/1043
从问题描述看来,这是库的一个限制,没有修复它的计划。其实是JavaScript本身的限制。它没有内置的 GUID 类型。图书馆没有给出任何关于这种情况的警告。
作为变通方法,您可以使用您发布的示例中的字符串或创建您自己的 GUID 类型,但仅使用 JS 的内置原始类型来定义它。
使用 asp.net 核心 2.2 和 angular 7,(asp.net核心:signalr 1.1.0 + angular:"@aspnet/signalr": " ^1.1.4")
在我尝试将字典发送到 angular 之前,它工作正常。当它尝试发送字典时断开连接。
Utils.js:209 [2019-12-29T11:09:11.959Z] Information: WebSocket connected to ws://localhost:64408/chat?id=6d-C7eu1X-Pv8t4-RwdbYg.
Utils.js:209 [2019-12-29T11:09:12.132Z] Information: Connection disconnected.
这些是我的代码:
InMemoryChatRoomServiceclass:
public class InMemoryChatRoomService : IChatRoomService
{
private readonly Dictionary<Guid, ChatRoom> _roomInfo = new Dictionary<Guid, ChatRoom>();
public Task<IReadOnlyDictionary<Guid, ChatRoom>> GetAllRooms()
{
return Task.FromResult(_roomInfo as IReadOnlyDictionary<Guid, ChatRoom>);
}
}
IChatroomService:
using SignalR.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SignalR
{
public interface IChatRoomService
{
Task<IReadOnlyDictionary<Guid, ChatRoom>> GetAllRooms();
}
}
ChatHub class:
using Microsoft.AspNetCore.SignalR;
using SignalR.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SignalR
{
public class ChatHub : Hub
{
private readonly IChatRoomService _chatRoomService;
public ChatHub(IChatRoomService ChatRoomService)
{
_chatRoomService = ChatRoomService;
}
public override async Task OnConnectedAsync()
{
await Clients.Caller.SendAsync("ActiveRooms", await _chatRoomService.GetAllRooms());
await base.OnConnectedAsync();
}
}
}
angular:
import { Component, OnInit } from '@angular/core';
import * as signalR from "@aspnet/signalr";
import { HttpClient } from "@angular/common/http";
import { MessagePacket } from './MessagePacket.model';
import { ChatService } from './chat.service';
import { ChatRoom } from './ChatRoom.model';
@Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.scss']
})
export class ChatComponent implements OnInit {
constructor(private http: HttpClient, private chatService: ChatService) { }
private hub: signalR.HubConnection;
rooms = [ ];
messagePackets: MessagePacket[] = [];
isConnected = false;
connectionAttempts = 0;
ipAddress = '';
typedMessage = '';
userChatName = 'salar';//todo: load user data
ngOnInit() {
//build connection
this.hub = new signalR.HubConnectionBuilder()
.withUrl('http://localhost:64408/chat')
.build();
//start connection
this.startConnection();
this.hub.on('ActiveRooms', (rooms ) => {
this.ActiveRooms(rooms)
});
//on disconnect
this.hub.onclose(h => {
this.isConnected = false;
setTimeout(x => this.startConnection(), 3000)
});
}
startConnection() {
this.connectionAttempts++;
console.log('Connecting!')
this.hub
.start()
.then(() => {
this.connectionAttempts = 0;
this.isConnected = true;
console.log('Connection started!');
console.log('Getting all rooms');
// this.hub.invoke("ActiveRooms");
})
.catch(err => {
if (this.connectionAttempts < 10) {
console.log(this.connectionAttempts + ' try for connection')
setTimeout(x => this.startConnection(), 3000)
} else {
console.log('Error while establishing connection. changed mode to manual')
}
});
}
ActiveRooms(rooms ) {
var x = '';
// this.rooms = rooms;
}
}
当我跟踪时,它会尝试发回字典,之后,信号器会断开连接并尝试再次连接。如果它不是字典而是像字符串或其他对象,它工作正常。
更新:
当我将字典的类型 GUID 更改为 STRING 时,一切正常:
public Task<IReadOnlyDictionary<string, ChatRoom>> GetAllRooms()
{
//type guid gives error so needs to be converted to string
Dictionary<string, ChatRoom> result = new Dictionary<string, ChatRoom>();
foreach (var room in _roomInfo)
{
result.Add(room.Key.ToString(), room.Value);
}
return Task.FromResult(result as IReadOnlyDictionary<string, ChatRoom>);
}
GUID 有问题。
SignalR 在想要 serialize/deserialize GUID 时遇到问题,并且它必须在 C# 端和 JS 端工作。 GUID 有点棘手。它是一个结构,而不是 class。它有二进制表示和字符串表示。
我发现了这个问题: https://github.com/aspnet/SignalR/issues/1043
从问题描述看来,这是库的一个限制,没有修复它的计划。其实是JavaScript本身的限制。它没有内置的 GUID 类型。图书馆没有给出任何关于这种情况的警告。
作为变通方法,您可以使用您发布的示例中的字符串或创建您自己的 GUID 类型,但仅使用 JS 的内置原始类型来定义它。