Search code examples
c#deserializationmicrosoft-teamsadaptive-cards

C# AdaptiveCards 1.2.4 problems with deserialization of simple card


I am using AdaptiveCards 1.2.4 from NuGet and there are some problems with deserialization. I was able to drill down and identify where the error comes from exactly and shortened the card to 2 column sets. The card is parsed with them separately but it's not with both at the same time.

Exception.Message = "Current error context error is different to requested error."
Exception.StackTrace = "   at 
Newtonsoft.Json.Serialization.JsonSerializerInternalBase.GetErrorContext(Object currentObject, Object 
member, String path, Exception error)
at Newtonsoft.Json.Serialization.JsonSerializerInternalBase.IsErrorHandled(Object currentObject, J 
JsonContract contract, Object keyValue, IJsonLineInfo lineInfo, String path, Exception ex)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type 
objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings 
settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at AdaptiveCards.AdaptiveCard.FromJson(String json)
at AdaptiveCardsDeserializationProblem.Program.Main(String[] args) in 
C:\Work\Demo\AdaptiveCardsDeserializationProblem\AdaptiveCardsDeserializationProblem\Startup.cs:line 
34"

This is a sample code that shows the issue.

        try
        {
            var problematicCard = "{\"type\":\"AdaptiveCard\",\"body\":[{\"type\":\"ColumnSet\",\"spacing\":\"None\",\"columns\":[{\"type\":\"Column\",\"style\":\"default\",\"items\":[{\"type\":\"FactSet\"}],\"width\":\"stretch\"}]},{\"type\":\"ColumnSet\",\"spacing\":\"None\",\"columns\":[{\"type\":\"Column\",\"style\":\"default\",\"items\":[{\"type\":\"FactSet\"}],\"width\":\"stretch\"}]}],\"version\":\"1.0\"}";
            var firstColumnSet = "{\"type\":\"AdaptiveCard\",\"body\":[{\"type\":\"ColumnSet\",\"spacing\":\"None\",\"columns\":[{\"type\":\"Column\",\"style\":\"default\",\"items\":[{\"type\":\"FactSet\"}],\"width\":\"stretch\"}]}],\"version\":\"1.0\"}";
            var secondColumnSet = "{\"type\":\"AdaptiveCard\",\"body\":[{\"type\":\"ColumnSet\",\"spacing\":\"None\",\"columns\":[{\"type\":\"Column\",\"style\":\"default\",\"items\":[{\"type\":\"FactSet\"}],\"width\":\"stretch\"}]}],\"version\":\"1.0\"}";

            var adaptiveCard = AdaptiveCard.FromJson(problematicCard);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw;
        }

This is the card's JSON -> https://pastebin.com/Ud4BZ33g

And this is how the card looks like in the adaptive cards designer

This is how the card looks like in the adaptive cards designer

It looks like it's throwing here.. https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs#L103


Solution

  • The best way to diagnose serialization/deserialization issues is to populate the object yourself and serialize it to see what json content would it generate. We expect the same json to deserialize back, without errors.

    In this case, we populate the exact object, and serialize it using the ToJson() method.

    We see that the only difference is

    Problematic:

    ... \"items\":[{\"type\":\"FactSet\"}],\"width\":\"stretch\"}]} ...
    

    Working:

    ... \"items\":[{\"type\":\"FactSet\", \"facts\": []}],\"width\":\"stretch\"}]} ...
    

    And yes, when changed to contain the facts empty array, the deserialization works, as expected.

    Hope this helps.