Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/dotnet/Library/AdaptiveCards/AdaptiveCard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public static AdaptiveCardParseResult FromJson(string json)
{
parseResult.Card = JsonConvert.DeserializeObject<AdaptiveCard>(json, new JsonSerializerSettings
{
ContractResolver = new WarningLoggingContractResolver(parseResult),
ContractResolver = new WarningLoggingContractResolver(parseResult, new ParseContext()),
Converters = { new StrictIntConverter() }
});
}
Expand Down
13 changes: 9 additions & 4 deletions source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace AdaptiveCards
{
public class AdaptiveCardConverter : JsonConverter, ILogWarnings
public class AdaptiveCardConverter : AdaptiveTypedBaseElementConverter, ILogWarnings
{
public List<AdaptiveWarning> Warnings { get; set; } = new List<AdaptiveWarning>();

Expand Down Expand Up @@ -62,16 +62,21 @@ 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();

ValidateJsonVersion(ref jObject);

if (new AdaptiveSchemaVersion(jObject.Value<string>("version")) > AdaptiveCard.KnownSchemaVersion)
{
return MakeFallbackTextCard(jObject);
}
}

/// this is needed when client calls JsonConvert.Deserializer 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace AdaptiveCards
{
public class AdaptiveFallbackConverter : JsonConverter, ILogWarnings
public class AdaptiveFallbackConverter : AdaptiveTypedBaseElementConverter, ILogWarnings
{
public List<AdaptiveWarning> Warnings { get; set; } = new List<AdaptiveWarning>();

Expand Down Expand Up @@ -103,7 +103,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)
Expand Down
14 changes: 12 additions & 2 deletions source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace AdaptiveCards
{
class AdaptiveInlinesConverter : JsonConverter
class AdaptiveInlinesConverter : AdaptiveTypedBaseElementConverter
{
public override bool CanRead => true;

Expand Down Expand Up @@ -39,7 +39,17 @@ 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)));

if(ParseContext == null) {
ParseContext = new ParseContext();
}

var adaptiveInline = JsonConvert.DeserializeObject<AdaptiveTextRun>(jobj.ToString(), new JsonSerializerSettings
{
ContractResolver = new WarningLoggingContractResolver(new AdaptiveCardParseResult(), ParseContext),
Converters = { new StrictIntConverter() }
});
arrayList.Add(adaptiveInline);
}
}
return arrayList;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

@shalinijoshi19 Shalini Joshi (shalinijoshi19) Oct 31, 2019 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Should be able to clean up the using's here to remove ones not being used in the file #Resolved

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks


In reply to: 341278562 [](ancestors = 341278562)


namespace AdaptiveCards
{
public abstract class AdaptiveTypedBaseElementConverter : JsonConverter

@shalinijoshi19 Shalini Joshi (shalinijoshi19) Oct 31, 2019 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Late but adding comments anyways; Good to have some class comments explainng why this wasnt needed for eg. Also do you need System.Threading.Tasks here? #Resolved

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure
and good catch! will remove it


In reply to: 341278327 [](ancestors = 341278327)

{
protected ParseContext parseContext;
public ParseContext ParseContext

@shalinijoshi19 Shalini Joshi (shalinijoshi19) Oct 31, 2019 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious: Wouldnt automatic properties work here?Also why is the local member (parseContext) declared as protected? Additionally why is ParseContext - the property a public property vs protected? #Resolved

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

o.k. will change to automatic property. it was intended that inherited object would be able to freely access this property, but automatic property makes more sense.


In reply to: 341280836 [](ancestors = 341280836)

{
get => parseContext;
set
{
parseContext = value;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

/// <summary>
/// A unique ID associated with the element. For Inputs the ID will be used as the key for Action.Submit response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace AdaptiveCards
/// <summary>
/// This handles using type field to instantiate strongly typed object on deserialization
/// </summary>
public class AdaptiveTypedElementConverter : JsonConverter, ILogWarnings
public class AdaptiveTypedElementConverter : AdaptiveTypedBaseElementConverter, ILogWarnings
{
public List<AdaptiveWarning> Warnings { get; set; } = new List<AdaptiveWarning>();

Expand Down Expand Up @@ -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) { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace AdaptiveCards
{
public class IgnoreEmptyItemsConverter<T> : JsonConverter
public class IgnoreEmptyItemsConverter<T> : AdaptiveTypedBaseElementConverter
{
public override bool CanConvert(Type objectType)
{
Expand Down
22 changes: 8 additions & 14 deletions source/dotnet/Library/AdaptiveCards/ParseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,18 @@

namespace AdaptiveCards
{
static class ParseContext
public class ParseContext
{
public static void Initialize()
{
elementIds = new Dictionary<string, List<AdaptiveInternalID>>();
idStack = new Stack<Tuple<string, AdaptiveInternalID, bool>>();
}

public enum ContextType { Element, Action };

public static ContextType Type { get; set; }
public ContextType Type { get; set; }

private static IDictionary<string, List<AdaptiveInternalID>> elementIds = new Dictionary<string, List<AdaptiveInternalID>>();
private IDictionary<string, List<AdaptiveInternalID>> elementIds = new Dictionary<string, List<AdaptiveInternalID>>();

private static Stack<Tuple<string, AdaptiveInternalID, bool>> idStack = new Stack<Tuple<string, AdaptiveInternalID, bool>>();
private Stack<Tuple<string, AdaptiveInternalID, bool>> idStack = new Stack<Tuple<string, AdaptiveInternalID, bool>>();

// 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))
{
Expand All @@ -31,7 +25,7 @@ public static void PushElement(string idJsonProperty, AdaptiveInternalID interna
idStack.Push(new Tuple<string, AdaptiveInternalID, bool>(idJsonProperty, internalId, AdaptiveFallbackConverter.IsInFallback));
}

public static AdaptiveInternalID PeekElement()
public AdaptiveInternalID PeekElement()
{
if (idStack.Count == 0)
{
Expand All @@ -42,7 +36,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();
Expand Down Expand Up @@ -121,7 +115,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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 converterWithContext)
{
converterWithContext.ParseContext = _parseContext;
}

if (converter is ILogWarnings logWarnings)
{
logWarnings.Warnings = _parseResult.Warnings;
Expand All @@ -46,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;
Expand Down
Loading