microsoft / microsoft/AdaptiveCards
[Rendering] Uncatchable Exception when rendering a card with an invalid image url which is auto sized
@jwoo-msft is already working on this.
Since Jun 29, 2023.
- Dominant language
- C#
- Stars
- 2k
- Forks
- 595
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 1
Description
Target Platforms
WPF
SDK Version
3.0.0
Application Name
In our own application using the wpf rendering library
Problem Description
We are trying to render cards in our WPF application and noticed there is an uncatchable exception thrown by the renderer in case we have an adaptive card with an image which points to an invalid url and only defines one dimension (e.g. only height for the element is defined).
It would be nice to at least be able to catch the excpetion but it seems it is thrown in a async method within the rendering process and thus i can't catch it.
The stracktrace we get is the following (reproducible by creating a new WPF application and using the example code from bellow):
System.InvalidOperationException: Nullable object must have a value.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Nullable`1.get_Value()
at AdaptiveCards.Rendering.Wpf.ImageExtensions.StretchConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.Activate(Object item)
at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
at System.Windows.Data.BindingExpression.AttachOverride(DependencyObject target, DependencyProperty dp)
at System.Windows.Data.BindingExpressionBase.OnAttach(DependencyObject d, DependencyProperty dp)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.Data.BindingOperations.SetBinding(DependencyObject target, DependencyProperty dp, BindingBase binding)
at System.Windows.FrameworkElement.SetBinding(DependencyProperty dp, BindingBase binding)
at AdaptiveCards.Rendering.Wpf.ImageExtensions.<SetSource>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.<ThrowAsync>b__6_0(Object state)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
at AdaptiveCards.App.Main()
Screenshots
No response
Card JSON
{
"type": "AdaptiveCard",
"body": [
{
"type": "Image",
"url": "http://adaptivecards.io/content/cats/non_existing.png",
"height": "50px"
}
],
"version": "1.1"
}
Sample Code Language
C#
Sample Code
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Windows;
using AdaptiveCards.Rendering.Wpf;
namespace AdaptiveCards
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
public MainWindow()
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");
InitializeComponent();
CreateCard();
}
private const string CardString = @"{
""type"": ""AdaptiveCard"",
""body"": [
{
""type"": ""Image"",
""url"": ""http://adaptivecards.io/content/cats/non_existing.png"",
""height"": ""50px""
}
],
""version"": ""1.1""
}";
private void CreateCard()
{
var card = AdaptiveCard.FromJson(CardString).Card;
try
{
// Create a card renderer
AdaptiveCardRenderer renderer = new AdaptiveCardRenderer();
// For fun, check the schema version this renderer supports
AdaptiveSchemaVersion schemaVersion = renderer.SupportedSchemaVersion;
// Render the card
RenderedAdaptiveCard renderedCard = renderer.RenderCard(card);
// Get the FrameworkElement
// Add this to your app's UI somewhere
FrameworkElement fe = renderedCard.FrameworkElement;
// (Optional) Check for any renderer warnings
// This includes things like an unknown element type found in the card
// Or the card exceeded the maximum number of supported actions, etc
IList<AdaptiveWarning> warnings = renderedCard.Warnings;
Grid.Children.Add(fe);
}
catch(Exception ex)
{
// Failed rendering
}
}
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.