emitter-io / csharp

Client library for emitter.io compatible with .Net, .Net MicroFramework and WinRT
http://emitter.io
Eclipse Public License 1.0
29 stars 21 forks source link

The given key 'key' was not present in the dictionary (at GenerateKey) #8

Open JCKodel opened 5 years ago

JCKodel commented 5 years ago

While running this code (using the Emitter nuget on a .net core console project):

var emitter = new Emitter.Connection();

emitter.Connect();

emitter.GenerateKey("MY_SECRET_KEY_COPIED_FROM_CONSOLE", "chat/", Emitter.Messages.EmitterKeyType.ReadWrite, (r) =>
{
        // This never runs
    Console.WriteLine(r.Status + ": " + r.Key);
});

this error is thrown:

Error: System.Collections.Generic.KeyNotFoundException: The given key 'key' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Emitter.Messages.KeygenResponse.FromJson(String json) in C:\projects\csharp-133tg\Emitter\Messages\KeygenResponse.cs:line 50
   at Emitter.Connection.OnMessageReceived(Object sender, MqttMsgPublishEventArgs e) in C:\projects\csharp-133tg\Emitter\Emitter.cs:line 427
JCKodel commented 5 years ago

Using the latest source code, the error remains. Debugging shows that Emitter responds to the keygen request this json:

{"status":401,"message":"the security key provided is not authorized to perform this operation"}

At KeygenResponse.cs, line 47, there is no error handling code written (it assumes the response will always have a "key" key, hence the exception):

public static KeygenResponse FromJson(string json)
{
        var map = JsonSerializer.DeserializeString(json) as Hashtable;
        var response = new KeygenResponse();

        response.Key = (string)map["key"];
        response.Channel = (string)map["channel"];
        response.Status = Convert.ToInt32(map["status"].ToString());

        return response;
}

The safest code would be:

public static KeygenResponse FromJson(string json)
{
        var map = JsonSerializer.DeserializeString(json) as Hashtable;
    var response = new KeygenResponse();
    object key;
    object channel;
    object message;
    object status;

    map.TryGetValue("key", out key);
    map.TryGetValue("channel", out channel);
    map.TryGetValue("message", out message);
    map.TryGetValue("status", out status);

    if(key != null) response.Key = (string)key;
    if(channel != null) response.Channel = (string)channel;
    if(status != null) response.Status = Convert.ToInt32(status);

    if(response.Status > 299 && message != null)
    {
        throw new EmitterException((EmitterEventCode)response.Status, (string)message);
    }

    return response;
}

That would give me a more meaningful error message (although is my first try with Emitter, I have no clue what is going on):

Error: Emitter.EmitterException: the security key provided is not authorized to perform this operation
   at Emitter.Messages.KeygenResponse.FromJson(String json) in C:\Temp\csharp-master\Emitter\Messages\KeygenResponse.cs:line 70
   at Emitter.Messages.KeygenResponse.FromBinary(Byte[] message) in C:\Temp\csharp-master\Emitter\Messages\KeygenResponse.cs:line 80
   at Emitter.Connection.OnMessageReceived(Object sender, MqttMsgPublishEventArgs e) in C:\Temp\csharp-master\Emitter\Emitter.cs:line 430