Skip to content

Commit

Permalink
[.NET] Add new OnDeserializingMissingVersion callback
Browse files Browse the repository at this point in the history
Fixes #3376
  • Loading branch information
paulcam206 committed Sep 17, 2019
1 parent 302b0d8 commit 45a4b1b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
8 changes: 8 additions & 0 deletions source/dotnet/Library/AdaptiveCards/AdaptiveCard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,14 @@ public bool ShouldSerializeJsonSchema()

public bool ShouldSerializeHeight() => this.Height?.ShouldSerializeAdaptiveHeight() == true;

/// <summary>
/// Callback that will be invoked should a null or empty version string is encountered. The callback may return an alternate version to use for parsing.
/// </summary>
/// <example>
/// AdaptiveCard.OnDeserializingMissingVersion = () => new AdaptiveSchemaVersion(0, 5);
/// </example>
public static Func<AdaptiveSchemaVersion> OnDeserializingMissingVersion { get; set; }

/// <summary>
/// Parse an AdaptiveCard from a JSON string
/// </summary>
Expand Down
45 changes: 34 additions & 11 deletions source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,52 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s

public override bool CanWrite => false;

private void ValidateJsonVersion(ref JObject jObject)
{
string exceptionMessage = "";
if (jObject.Value<string>("version") == null)
{
exceptionMessage = "Could not parse required key: version. It was not found.";
}

// If this is the root AdaptiveCard and missing a version we fail parsing.
// The depth checks that cards within a Action.ShowCard don't require the version
if (jObject.Value<string>("version") == "")
{
exceptionMessage = "Property is required but was found empty: version";
}

if (!String.IsNullOrEmpty(exceptionMessage))
{
if (AdaptiveCard.OnDeserializingMissingVersion == null)
{
// no handler registered for dealing with missing/empty version. best just throw...
throw new AdaptiveSerializationException(exceptionMessage);
}
else
{
// caller wants to override version semantics
var overriddenVersion = AdaptiveCard.OnDeserializingMissingVersion();
jObject["version"] = overriddenVersion.ToString();
}
}
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);

if (jObject.Value<string>("type") != AdaptiveCard.TypeName)
{
throw new AdaptiveSerializationException($"Property 'type' must be '{AdaptiveCard.TypeName}'");
}

if (reader.Depth == 0)
{
// Needed for ID collision detection after fallback was introduced
ParseContext.Initialize();

if (jObject.Value<string>("version") == null)
{
throw new AdaptiveSerializationException("Could not parse required key: version. It was not found.");
}

// If this is the root AdaptiveCard and missing a version we fail parsing.
// The depth checks that cards within a Action.ShowCard don't require the version
if (jObject.Value<string>("version") == "")
{
throw new AdaptiveSerializationException("Property is required but was found empty: version");
}
ValidateJsonVersion(ref jObject);

if (new AdaptiveSchemaVersion(jObject.Value<string>("version")) > AdaptiveCard.KnownSchemaVersion)
{
Expand Down
2 changes: 0 additions & 2 deletions source/dotnet/Samples/WPFVisualizer/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public MainWindow()
});
}


Renderer = new AdaptiveCardRenderer()
{
Resources = Resources
Expand Down Expand Up @@ -122,7 +121,6 @@ private void RenderCard()

try
{

AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(CardPayload);

AdaptiveCard card = parseResult.Card;
Expand Down
11 changes: 11 additions & 0 deletions source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,18 @@ public void TestParsingInvalidCardMissingVersion()
}
]
}";
// By default we should be throwing an exception when no version present.
Assert.ThrowsException<AdaptiveSerializationException>(() => AdaptiveCard.FromJson(json));

// Or we can supply a replacement version to use
AdaptiveCard.OnDeserializingMissingVersion = () => new AdaptiveSchemaVersion(0, 5);
var card = AdaptiveCard.FromJson(json);
Assert.AreEqual(new AdaptiveSchemaVersion(0, 5), card.Card.Version);

// But make sure that if the callback throws an exception that it is allowed through
AdaptiveCard.OnDeserializingMissingVersion = () => throw new Exception("test exception");
Assert.ThrowsException<Exception>(() => AdaptiveCard.FromJson(json));
AdaptiveCard.OnDeserializingMissingVersion = null;
}

[TestMethod]
Expand Down

0 comments on commit 45a4b1b

Please sign in to comment.