Search code examples
c#json.netazureservicebusjson-deserialization

Service Bus SendMessageAsync failing when ApplicationProperties is set with values from a Json Deserialized Dictionary<string,object>


I have a scenario I need to set ApplicationProperties to a Azure Service Bus message. I have dictionary of key, value type <string,object>. I also use System.Text.Json for deserializing the payload from request.

I tried to recreate issue. I have a method which gives me the body payload. here I named it GetParams. It gives a nullable Dictionary of <string,object>

 IDictionary<string, object>? GetParams()
{
    bool shouldReturnParameters = true;
    if (shouldReturnParameters)
    {
        string jsonString = "{\"Parameter1\": 123, \"Parameter2\": \"Some value\"}";
        var parameters = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);

        return parameters;
    }
    else
    {
        return null;
    }
} 

Now in main method I try to send the message

    var data = Encoding.UTF8.GetBytes(json);
    var message = new ServiceBusMessage(data);
    IDictionary<string, object>? params = GetParams();
    if (params != null)
    {
        foreach (var param in params)
        {
            message.ApplicationProperties[param.Key] = param.Value;
        }
    }

    await sender.SendMessageAsync(message); //ERROR!

Now I get unhandled exception System.Runtime.Serialization.SerializationException: Serialization failed due to an unsupported type, System.Text.Json.JsonElement.

When I debug the code param.Value had a property called ValueKind apart from the value. When I just hardode the values when assigning values like ApplicationProperties["Parameter1"] = 123 then it worked.

So is there a general solution for this problem. Do I have to do .toString() and do if checks to check each type like string, number, boolean etc and then parse the value to that type.


Solution

  • ApplicationProperties is of Dictionary<string, object> type. Individual values can only be made up of simple types Azure Service Bus allows as documentated.

    • string
    • bool
    • byte
    • sbyte
    • short
    • short
    • int
    • unit
    • long
    • long
    • float
    • decimal
    • double
    • char
    • Guid
    • DateTime
    • DateTimeOffset
    • Stream
    • Uri
    • TimeSpan

    If you need to assign an unsupported type, you'll need to serialize and store it as a string