From 0bac9343e230dcd4adb8e8c12b849e48127da246 Mon Sep 17 00:00:00 2001 From: nesalang Date: Tue, 29 Oct 2019 15:37:00 -0700 Subject: [PATCH 1/7] made parse context not static; need to fix the internal id being null when showcard is parsed --- .../dotnet/Library/AdaptiveCards/AdaptiveCard.cs | 2 +- .../AdaptiveCards/AdaptiveCardConverter.cs | 2 +- .../AdaptiveCards/AdaptiveFallbackConverter.cs | 5 +++-- .../AdaptiveCards/AdaptiveTypedElement.cs | 2 +- .../AdaptiveTypedElementConverter.cs | 2 +- .../dotnet/Library/AdaptiveCards/ParseContext.cs | 16 ++++++++-------- .../WarningLoggingContractResolver.cs | 9 ++++++++- 7 files changed, 23 insertions(+), 15 deletions(-) diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveCard.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveCard.cs index bfab1d1b93..e91dbba92d 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveCard.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveCard.cs @@ -238,7 +238,7 @@ public static AdaptiveCardParseResult FromJson(string json) { parseResult.Card = JsonConvert.DeserializeObject(json, new JsonSerializerSettings { - ContractResolver = new WarningLoggingContractResolver(parseResult), + ContractResolver = new WarningLoggingContractResolver(parseResult, new ParseContext()), Converters = { new StrictIntConverter() } }); } diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs index e8654655f8..b68150f0a0 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs @@ -9,7 +9,7 @@ namespace AdaptiveCards { - public class AdaptiveCardConverter : JsonConverter, ILogWarnings + public class AdaptiveCardConverter : AdaptiveTypedBaseElementConverter, ILogWarnings { public List Warnings { get; set; } = new List(); diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveFallbackConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveFallbackConverter.cs index 6b991c874f..44e7d91c0b 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveFallbackConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveFallbackConverter.cs @@ -2,10 +2,11 @@ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace AdaptiveCards { - public class AdaptiveFallbackConverter : JsonConverter, ILogWarnings + public class AdaptiveFallbackConverter : AdaptiveTypedBaseElementConverter, ILogWarnings { public List Warnings { get; set; } = new List(); @@ -103,7 +104,7 @@ public override bool CanConvert(Type objectType) return result; } - public static AdaptiveFallbackElement ParseFallback(JToken fallbackJSON, JsonSerializer serializer, string objectId, AdaptiveInternalID internalId) + public AdaptiveFallbackElement ParseFallback(JToken fallbackJSON, JsonSerializer serializer, string objectId, AdaptiveInternalID internalId) { // Handle fallback as a string ("drop") if (fallbackJSON.Type == JTokenType.String) diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElement.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElement.cs index 5b8cc0462a..0f96ea0dca 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElement.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElement.cs @@ -46,7 +46,7 @@ public abstract class AdaptiveTypedElement public AdaptiveFallbackElement Fallback { get; set; } [JsonIgnore] - public AdaptiveInternalID InternalID { get; } = ParseContext.PeekElement(); + public AdaptiveInternalID InternalID { get; }// = ParseContext.PeekElement(); /// /// A unique ID associated with the element. For Inputs the ID will be used as the key for Action.Submit response diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElementConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElementConverter.cs index 707c66eafc..31b09c38b0 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElementConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElementConverter.cs @@ -12,7 +12,7 @@ namespace AdaptiveCards /// /// This handles using type field to instantiate strongly typed object on deserialization /// - public class AdaptiveTypedElementConverter : JsonConverter, ILogWarnings + public class AdaptiveTypedElementConverter : AdaptiveTypedBaseElementConverter, ILogWarnings { public List Warnings { get; set; } = new List(); diff --git a/source/dotnet/Library/AdaptiveCards/ParseContext.cs b/source/dotnet/Library/AdaptiveCards/ParseContext.cs index da90ec5db4..37276a0411 100644 --- a/source/dotnet/Library/AdaptiveCards/ParseContext.cs +++ b/source/dotnet/Library/AdaptiveCards/ParseContext.cs @@ -5,9 +5,9 @@ namespace AdaptiveCards { - static class ParseContext + public class ParseContext { - public static void Initialize() + public void Initialize() { elementIds = new Dictionary>(); idStack = new Stack>(); @@ -17,12 +17,12 @@ public enum ContextType { Element, Action }; public static ContextType Type { get; set; } - private static IDictionary> elementIds = new Dictionary>(); + private IDictionary> elementIds = new Dictionary>(); - private static Stack> idStack = new Stack>(); + private Stack> idStack = new Stack>(); // Push the provided state on to our ID stack - public static void PushElement(string idJsonProperty, AdaptiveInternalID internalId) + public void PushElement(string idJsonProperty, AdaptiveInternalID internalId) { if (internalId.Equals(AdaptiveInternalID.Invalid)) { @@ -31,7 +31,7 @@ public static void PushElement(string idJsonProperty, AdaptiveInternalID interna idStack.Push(new Tuple(idJsonProperty, internalId, AdaptiveFallbackConverter.IsInFallback)); } - public static AdaptiveInternalID PeekElement() + public AdaptiveInternalID PeekElement() { if (idStack.Count == 0) { @@ -42,7 +42,7 @@ public static AdaptiveInternalID PeekElement() } // Pop the last id off our stack and perform validation - public static void PopElement() + public void PopElement() { // about to pop an element off the stack. perform collision list maintenance and detection. var idsToPop = idStack.Peek(); @@ -121,7 +121,7 @@ public static void PopElement() // Walk stack looking for first element to be marked fallback (which isn't the ID we're supposed to skip), then // return its internal ID. If none, return an invalid ID. (see comment above) - public static AdaptiveInternalID GetNearestFallbackID(AdaptiveInternalID skipID) + public AdaptiveInternalID GetNearestFallbackID(AdaptiveInternalID skipID) { foreach (var curElement in idStack) { diff --git a/source/dotnet/Library/AdaptiveCards/WarningLoggingContractResolver.cs b/source/dotnet/Library/AdaptiveCards/WarningLoggingContractResolver.cs index ce6d90cd71..370fc4013b 100644 --- a/source/dotnet/Library/AdaptiveCards/WarningLoggingContractResolver.cs +++ b/source/dotnet/Library/AdaptiveCards/WarningLoggingContractResolver.cs @@ -13,16 +13,23 @@ namespace AdaptiveCards internal class WarningLoggingContractResolver : DefaultContractResolver { private readonly AdaptiveCardParseResult _parseResult; + private ParseContext _parseContext; - public WarningLoggingContractResolver(AdaptiveCardParseResult parseResult) + public WarningLoggingContractResolver(AdaptiveCardParseResult parseResult, ParseContext parseContext) { _parseResult = parseResult; + _parseContext = parseContext; } protected override JsonConverter ResolveContractConverter(Type type) { var converter = base.ResolveContractConverter(type); + if (converter is AdaptiveTypedBaseElementConverter) + { + ((AdaptiveTypedBaseElementConverter)converter).ParseContext = _parseContext; + } + if (converter is ILogWarnings logWarnings) { logWarnings.Warnings = _parseResult.Warnings; From 474884a1f01631b6fb3e0946ced7fd6f61921be1 Mon Sep 17 00:00:00 2001 From: nesalang Date: Tue, 29 Oct 2019 15:43:31 -0700 Subject: [PATCH 2/7] adding missing file --- .../AdaptiveTypedBaseElementConverter.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 source/dotnet/Library/AdaptiveCards/AdaptiveTypedBaseElementConverter.cs diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedBaseElementConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedBaseElementConverter.cs new file mode 100644 index 0000000000..02ff7ccd6c --- /dev/null +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedBaseElementConverter.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AdaptiveCards +{ + public abstract class AdaptiveTypedBaseElementConverter : JsonConverter + { + protected ParseContext parseContext; + public ParseContext ParseContext + { + get => parseContext; + set + { + parseContext = value; + } + } + } +} From 52e882ffad66cee2f66e9df3d0e3e1a7cdfff56d Mon Sep 17 00:00:00 2001 From: nesalang Date: Tue, 29 Oct 2019 17:33:09 -0700 Subject: [PATCH 3/7] add parse context for property parsing --- .../AdaptiveCards/WarningLoggingContractResolver.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/dotnet/Library/AdaptiveCards/WarningLoggingContractResolver.cs b/source/dotnet/Library/AdaptiveCards/WarningLoggingContractResolver.cs index 370fc4013b..1eda59fa2a 100644 --- a/source/dotnet/Library/AdaptiveCards/WarningLoggingContractResolver.cs +++ b/source/dotnet/Library/AdaptiveCards/WarningLoggingContractResolver.cs @@ -25,9 +25,9 @@ protected override JsonConverter ResolveContractConverter(Type type) { var converter = base.ResolveContractConverter(type); - if (converter is AdaptiveTypedBaseElementConverter) + if (converter is AdaptiveTypedBaseElementConverter converterWithContext) { - ((AdaptiveTypedBaseElementConverter)converter).ParseContext = _parseContext; + converterWithContext.ParseContext = _parseContext; } if (converter is ILogWarnings logWarnings) @@ -53,6 +53,11 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ converter.Warnings = _parseResult.Warnings; } + if (property?.Converter is AdaptiveTypedBaseElementConverter converterWithContext) + { + converterWithContext.ParseContext = _parseContext; + } + if (property?.MemberConverter is ILogWarnings memberConverter) { memberConverter.Warnings = _parseResult.Warnings; From 9eb0598be34ebafd4d4c33c5cfa27df0f3a6a263 Mon Sep 17 00:00:00 2001 From: nesalang Date: Tue, 29 Oct 2019 17:56:19 -0700 Subject: [PATCH 4/7] work in progress --- .../Library/AdaptiveCards/AdaptiveCardConverter.cs | 9 ++++++++- .../Library/AdaptiveCards/AdaptiveInlinesConverter.cs | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs index b68150f0a0..e44dfb4964 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs @@ -63,7 +63,14 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist if (reader.Depth == 0) { // Needed for ID collision detection after fallback was introduced - ParseContext.Initialize(); + if (ParseContext == null) + { + ParseContext = new ParseContext(); + } + else + { + ParseContext.Initialize(); + } ValidateJsonVersion(ref jObject); diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs index fcd2036e2b..569e20cfc4 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs @@ -39,7 +39,13 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { throw new AdaptiveSerializationException($"Property 'type' must be '{AdaptiveTextRun.TypeName}'"); } - arrayList.Add((AdaptiveInline)jobj.ToObject(typeof(AdaptiveTextRun))); + //arrayList.Add((AdaptiveInline)jobj.ToObject(typeof(AdaptiveTextRun))); + var adaptiveInline = JsonConvert.DeserializeObject(jobj.ToString(), new JsonSerializerSettings + { + ContractResolver = new WarningLoggingContractResolver(new AdaptiveCardParseResult(), new ParseContext()), + Converters = { new StrictIntConverter() } + }); + arrayList.Add((AdaptiveInline)adaptiveInline); } } return arrayList; From 97e3834796f8017164cd276057e6aee2ae658bc3 Mon Sep 17 00:00:00 2001 From: nesalang Date: Tue, 29 Oct 2019 19:34:23 -0700 Subject: [PATCH 5/7] fixes concurrency issue during parsing --- .../AdaptiveCards/AdaptiveCardConverter.cs | 18 +-- .../AdaptiveCards/AdaptiveTypedElement.cs | 2 +- .../AdaptiveTypedElementConverter.cs | 1 + .../IgnoreEmptyItemsConverter.cs | 2 +- .../Library/AdaptiveCards/ParseContext.cs | 2 +- .../AdaptiveCardApiTests.cs | 148 +++++++++++++++++- 6 files changed, 159 insertions(+), 14 deletions(-) diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs index e44dfb4964..fd62ff9bb2 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs @@ -62,16 +62,6 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist if (reader.Depth == 0) { - // Needed for ID collision detection after fallback was introduced - if (ParseContext == null) - { - ParseContext = new ParseContext(); - } - else - { - ParseContext.Initialize(); - } - ValidateJsonVersion(ref jObject); if (new AdaptiveSchemaVersion(jObject.Value("version")) > AdaptiveCard.KnownSchemaVersion) @@ -79,6 +69,14 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist return MakeFallbackTextCard(jObject); } } + + /// this is needed when client calls Deserailizer method, we need this contract resolver, + /// so we can pass ParseContext + if (!(serializer.ContractResolver is WarningLoggingContractResolver)) + { + serializer.ContractResolver = new WarningLoggingContractResolver(new AdaptiveCardParseResult(), new ParseContext()); + } + var typedElementConverter = serializer.ContractResolver.ResolveContract(typeof(AdaptiveTypedElement)).Converter; var card = (AdaptiveCard)typedElementConverter.ReadJson(jObject.CreateReader(), objectType, existingValue, serializer); diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElement.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElement.cs index 0f96ea0dca..c457726b41 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElement.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElement.cs @@ -46,7 +46,7 @@ public abstract class AdaptiveTypedElement public AdaptiveFallbackElement Fallback { get; set; } [JsonIgnore] - public AdaptiveInternalID InternalID { get; }// = ParseContext.PeekElement(); + public AdaptiveInternalID InternalID { get; set; } /// /// A unique ID associated with the element. For Inputs the ID will be used as the key for Action.Submit response diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElementConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElementConverter.cs index 31b09c38b0..c656cdd4c7 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElementConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedElementConverter.cs @@ -98,6 +98,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist try { serializer.Populate(jObject.CreateReader(), result); + result.InternalID = internalID; } catch (JsonSerializationException) { } diff --git a/source/dotnet/Library/AdaptiveCards/IgnoreEmptyItemsConverter.cs b/source/dotnet/Library/AdaptiveCards/IgnoreEmptyItemsConverter.cs index bbee84585f..724e327af6 100644 --- a/source/dotnet/Library/AdaptiveCards/IgnoreEmptyItemsConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/IgnoreEmptyItemsConverter.cs @@ -9,7 +9,7 @@ namespace AdaptiveCards { - public class IgnoreEmptyItemsConverter : JsonConverter + public class IgnoreEmptyItemsConverter : AdaptiveTypedBaseElementConverter { public override bool CanConvert(Type objectType) { diff --git a/source/dotnet/Library/AdaptiveCards/ParseContext.cs b/source/dotnet/Library/AdaptiveCards/ParseContext.cs index 37276a0411..485a89f399 100644 --- a/source/dotnet/Library/AdaptiveCards/ParseContext.cs +++ b/source/dotnet/Library/AdaptiveCards/ParseContext.cs @@ -15,7 +15,7 @@ public void Initialize() public enum ContextType { Element, Action }; - public static ContextType Type { get; set; } + public ContextType Type { get; set; } private IDictionary> elementIds = new Dictionary>(); diff --git a/source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs b/source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs index 2812747910..35eeae03e5 100644 --- a/source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs +++ b/source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Collections; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json; +using System.Threading.Tasks; namespace AdaptiveCards.Test { @@ -1244,6 +1244,152 @@ public void TestParsingRichTextBlockWithInvalidInlineType() StringAssert.Contains(ex.Message, "Property 'type' must be 'TextRun'"); + } + void RenderCardTask(string payload) + { + AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(payload); + } + + [TestMethod] + public void TestConcurrentParsing() + { + // card with invalid inline type + var adaptiveCard = +@"{ + ""$schema"": ""http://adaptivecards.io/schemas/adaptive-card.json"", + ""type"": ""AdaptiveCard"", + ""version"": ""1.0"", + ""body"": [ + { + ""type"": ""TextBlock"", + ""text"": ""Publish Adaptive Card schema"", + ""weight"": ""bolder"", + ""size"": ""medium"" + }, + { + ""type"": ""ColumnSet"", + ""columns"": [ + { + ""type"": ""Column"", + ""width"": ""auto"", + ""items"": [ + { + ""type"": ""Image"", + ""url"": ""https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg"", + ""size"": ""small"", + ""style"": ""person"" + } + ] + }, + { + ""type"": ""Column"", + ""width"": ""stretch"", + ""items"": [ + { + ""type"": ""TextBlock"", + ""text"": ""Matt Hidinger"", + ""weight"": ""bolder"", + ""wrap"": true + }, + { + ""type"": ""TextBlock"", + ""spacing"": ""none"", + ""text"": ""Created {{DATE(2017-02-14T06:08:39Z, SHORT)}}"", + ""isSubtle"": true, + ""wrap"": true + } + ] + } + ] + }, + { + ""type"": ""TextBlock"", + ""text"": ""Now that we have defined the main rules and features of the format, we need to produce a schema and publish it to GitHub. The schema will be the starting point of our reference documentation."", + ""wrap"": true + }, + { + ""type"": ""FactSet"", + ""facts"": [ + { + ""title"": ""Board:"", + ""value"": ""Adaptive Card"" + }, + { + ""title"": ""List:"", + ""value"": ""Backlog"" + }, + { + ""title"": ""Assigned to:"", + ""value"": ""Matt Hidinger"" + }, + { + ""title"": ""Due date:"", + ""value"": ""Not set"" + } + ] + } + ], + ""actions"": [ + { + ""type"": ""Action.ShowCard"", + ""title"": ""Set due date"", + ""card"": { + ""type"": ""AdaptiveCard"", + ""body"": [ + { + ""type"": ""Input.Date"", + ""id"": ""dueDate"" + } + ], + ""actions"": [ + { + ""type"": ""Action.Submit"", + ""title"": ""OK"" + } + ] + } + }, + { + ""type"": ""Action.ShowCard"", + ""title"": ""Comment"", + ""card"": { + ""type"": ""AdaptiveCard"", + ""body"": [ + { + ""type"": ""Input.Text"", + ""id"": ""comment"", + ""isMultiline"": true, + ""placeholder"": ""Enter your comment"" + } + ], + ""actions"": [ + { + ""type"": ""Action.Submit"", + ""title"": ""OK"" + } + ] + } + } + ] +}"; + List tasks = new List(); + for (var i = 0; i < 10; i++) + { + var payload = adaptiveCard; + var task = Task.Run(() => { RenderCardTask(payload); }); + tasks.Add(task); + } + + try + { + Task.WaitAll(tasks.ToArray()); + } + catch + { + // it's perfectly fine card. if there is exception, it is due to concurreny + // as it's the only variable. + Assert.Fail(); + } } } } From ab00f52ff54226f2769080944c0460a370e3c963 Mon Sep 17 00:00:00 2001 From: nesalang Date: Tue, 29 Oct 2019 19:54:48 -0700 Subject: [PATCH 6/7] minor fix --- source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs index 569e20cfc4..86b284f669 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs @@ -39,7 +39,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { throw new AdaptiveSerializationException($"Property 'type' must be '{AdaptiveTextRun.TypeName}'"); } - //arrayList.Add((AdaptiveInline)jobj.ToObject(typeof(AdaptiveTextRun))); + var adaptiveInline = JsonConvert.DeserializeObject(jobj.ToString(), new JsonSerializerSettings { ContractResolver = new WarningLoggingContractResolver(new AdaptiveCardParseResult(), new ParseContext()), From 6b602620128386b987327656d7f00316ac4d2807 Mon Sep 17 00:00:00 2001 From: nesalang Date: Wed, 30 Oct 2019 13:25:40 -0700 Subject: [PATCH 7/7] updated PR per CR comments --- .../Library/AdaptiveCards/AdaptiveCardConverter.cs | 2 +- .../Library/AdaptiveCards/AdaptiveFallbackConverter.cs | 1 - .../Library/AdaptiveCards/AdaptiveInlinesConverter.cs | 10 +++++++--- .../AdaptiveCards/AdaptiveTypedBaseElementConverter.cs | 2 ++ source/dotnet/Library/AdaptiveCards/ParseContext.cs | 6 ------ .../Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs | 6 +++++- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs index fd62ff9bb2..dc11d6dfc2 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs @@ -70,7 +70,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist } } - /// this is needed when client calls Deserailizer method, we need this contract resolver, + /// this is needed when client calls JsonConvert.Deserializer method, we need this contract resolver, /// so we can pass ParseContext if (!(serializer.ContractResolver is WarningLoggingContractResolver)) { diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveFallbackConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveFallbackConverter.cs index 44e7d91c0b..3696699890 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveFallbackConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveFallbackConverter.cs @@ -2,7 +2,6 @@ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; namespace AdaptiveCards { diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs index 86b284f669..13cc2f2d72 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs @@ -8,7 +8,7 @@ namespace AdaptiveCards { - class AdaptiveInlinesConverter : JsonConverter + class AdaptiveInlinesConverter : AdaptiveTypedBaseElementConverter { public override bool CanRead => true; @@ -40,12 +40,16 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist throw new AdaptiveSerializationException($"Property 'type' must be '{AdaptiveTextRun.TypeName}'"); } + if(ParseContext == null) { + ParseContext = new ParseContext(); + } + var adaptiveInline = JsonConvert.DeserializeObject(jobj.ToString(), new JsonSerializerSettings { - ContractResolver = new WarningLoggingContractResolver(new AdaptiveCardParseResult(), new ParseContext()), + ContractResolver = new WarningLoggingContractResolver(new AdaptiveCardParseResult(), ParseContext), Converters = { new StrictIntConverter() } }); - arrayList.Add((AdaptiveInline)adaptiveInline); + arrayList.Add(adaptiveInline); } } return arrayList; diff --git a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedBaseElementConverter.cs b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedBaseElementConverter.cs index 02ff7ccd6c..87e074eb58 100644 --- a/source/dotnet/Library/AdaptiveCards/AdaptiveTypedBaseElementConverter.cs +++ b/source/dotnet/Library/AdaptiveCards/AdaptiveTypedBaseElementConverter.cs @@ -1,3 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. using Newtonsoft.Json; using System; using System.Collections.Generic; diff --git a/source/dotnet/Library/AdaptiveCards/ParseContext.cs b/source/dotnet/Library/AdaptiveCards/ParseContext.cs index 485a89f399..444213896b 100644 --- a/source/dotnet/Library/AdaptiveCards/ParseContext.cs +++ b/source/dotnet/Library/AdaptiveCards/ParseContext.cs @@ -7,12 +7,6 @@ namespace AdaptiveCards { public class ParseContext { - public void Initialize() - { - elementIds = new Dictionary>(); - idStack = new Stack>(); - } - public enum ContextType { Element, Action }; public ContextType Type { get; set; } diff --git a/source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs b/source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs index 35eeae03e5..fcf3d5aef7 100644 --- a/source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs +++ b/source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs @@ -1245,9 +1245,13 @@ public void TestParsingRichTextBlockWithInvalidInlineType() StringAssert.Contains(ex.Message, "Property 'type' must be 'TextRun'"); } - void RenderCardTask(string payload) + void RenderCardTask(string payload) { AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(payload); + if (parseResult.Warnings.Count != 0) + { + throw new Exception("parse failed"); + } } [TestMethod]