SignalR如何接收自定义数据类型?

时间:2019-04-15 12:08:45

标签: c# asp.net-core signalr

我正在使用SignalR和Asp.Net Core 2.2的服务器上工作。

我在服务器端有一个函数,可以接收3个参数,其中2个是可选的。 SignalR不支持此功能。但是要解决这个问题,我创建了一个用作自定义数据类型的类。

https://github.com/aspnet/AspNetCore/issues/8853

但是当我通过客户端调用该函数时,出现此错误:

Failed to invoke hub method 'CreateRoom'.
System.IO.InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked. ---> Newtonsoft.Json.JsonSerializationException: Error converting value 2 to type 'GameServer.Classes.CreateParams'. Path '[0]', line 1, position 15. ---> System.ArgumentException: Could not cast or convert from System.Int64 to GameServer.Classes.CreateParams.
   at Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(Object value, Type initialType, Type targetType) in /_/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs:line 616
   at Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(Object initialValue, CultureInfo culture, Type targetType) in /_/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs:line 587
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 982
   --- End of inner exception stack trace ---
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 989
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 167
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in /_/Src/Newtonsoft.Json/JsonSerializer.cs:line 907
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer) in /_/Src/Newtonsoft.Json/Linq/JToken.cs:line 2070
   at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindArguments(JArray args, IReadOnlyList`1 paramTypes)
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindArguments(JArray args, IReadOnlyList`1 paramTypes)
   at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.ParseMessage(Utf8BufferTextReader textReader, IInvocationBinder binder)

这是我的代码。

服务器端功能的开始。

GameHub.cs

public async Task CreateRoom(CreateParams data)
        {
            Log.Information("CreateRoom is called with Game: {0}, RoomName: {1}", data.Game, data.RoomName);

            try
            {
                int _MaxUsers = 2;
                if (data.MaxUsers != null)
                {
                    if (data.MaxUsers <= 2)
                    {
                        _MaxUsers = 2;
                    }
                    else
                    {
                        _MaxUsers = (int)data.MaxUsers;
                    }
                }

自定义课程

CreateParams

public class CreateParams
    {
        public string Game { get; set; }
        public string RoomName { get; set; }
        public int? MaxUsers { get; set; }
    }

客户

connection.invoke("CreateRoom", (gameType, lobbyName, maxUsers));

我不知道为什么会这样。 我希望你们能帮助我。

编辑

我尝试了你给我的东西,但是出现了这个错误:

Source: System.Collections.Concurrent, Method: ThrowKeyNullException, Error: Value cannot be null.
Parameter name: key, Stack Trace:    at System.Collections.Concurrent.ConcurrentDictionary`2.ThrowKeyNullException()
   at System.Collections.Concurrent.ConcurrentDictionary`2.TryGetValue(TKey key, TValue& value)
   at System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key)
   at GameServer.Hubs.GameHub.CreateRoom(CreateParams data) in projectlocation\GameServer\GameServer\Hubs\GameHub.cs:line 149
2019-04-15 14:34:50.504 +02:00 [ERR] Failed to invoke hub method 'CreateRoom'.
System.ArgumentNullException: Value cannot be null.
Parameter name: key
   at System.Collections.Concurrent.ConcurrentDictionary`2.ThrowKeyNullException()
   at System.Collections.Concurrent.ConcurrentDictionary`2.TryGetValue(TKey key, TValue& value)
   at System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key)
   at GameServer.Hubs.GameHub.CreateRoom(CreateParams data) in projectlocation\GameHub.cs:line 149
   at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.ExecuteHubMethod(ObjectMethodExecutor methodExecutor, THub hub, Object[] arguments)
   at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.Invoke(HubMethodDescriptor descriptor, HubConnectionContext connection, HubMethodInvocationMessage hubMethodInvocationMessage, Boolean isStreamedInvocation)

我记录了响应,并且所有参数都为空

2 个答案:

答案 0 :(得分:1)

您的客户端发送了错误的参数。您发送gameType,lobbyName和maxUsers,但该类需要Game,RoomName,MaxUsers

const params={
  Game: gameType,
  RoomName: lobbyName,
  MaxUsers: maxUsers
}
connection.invoke("CreateRoom", params);

应该解决它。

答案 1 :(得分:0)

在客户端创建一个json对象,如下所示:

const param={
 gameType:gameType,
 lobbyName: lobbyName,
 maxUsers: maxUsers
}

然后,将该对象传递给调用方法,如下所示:

connection.invoke("CreateRoom", param);

希望这会有所帮助。