Archive
Gotcha: Image component not loading remote URLs during debugging
At ClipFlair’s Image component I use the following XAML to make it show an image from a URL that its ViewModel holds at a property named “Source”, of type Uri (URI = Uniform or Universal Resource Identifier in W3C parlance, something like a superset of the old classic URLs).
<Image Name="imgContent"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Source="{Binding Source, Mode=OneWay}"
Stretch="{Binding Stretch, Mode=OneWay}"
>
I’ve had issues in the past with that component not loading an image, a tricky issue was when I had used Mode=TwoWay when data-binding to Source property – that was disastrous, since the Source property expects an ImageSource and just “plays it clever” internally, also accepting a conversion from a Uri. So when doing reverse binding too, you’d end up getting a null value at respective the ViewModel property.
So when it recently started not showing the test image (from a remote URL) that I had been using, I started wondering if it was some regression of that older bug, but couldn’t find some change in the respective code, plus in the Visual Studio XAML designer the component would load and display the remote image fine.
It turned out to be an issue with Silverlight’s security policy regarding cross-site access. The Image control is supposed to be able to load images from any remote URL (without the remote web server needing to have a ClientAccessPolicy.xml file for example to allow it, as is the case with the WebClient class), however I had recently found out that if at your Silverlight project you have selected at the “Debug” tab the “Dynamically generate a test page” option, the Image control wouldn’t load remote images.
What I didn’t know was that even the “Out-of-browser application option there won’t let the Image control load remote images if you don’t select the web project that goes with your Silverlight project (supposing you have them in the same Visual Studio solution), but you happen to select your Silverlight project instead from the dropdown list.
I had changed that option without thinking it might cause an issue while doing other changes in the project. That’s why one should try to do a minimal set of related changes only and test again thoroughly each time (if only they had the time available to do it), so that they can spot such issues early and be able to relate newly introduced bugs to the recent small set of changes, helping to track down the exact change that caused the unwanted behaviour.
Can’t step-through Silverlight file dialogs with Visual Studio debugger
While stepping through “ShowDialog()” method of OpenFileDialog with Visual Studio 2010 debugger, at the Silverlight code pictured below (for loading a ClipFlair window’s stored options), I got a “Dialogs must be user-initiated” exception. Same behaviour will be shown with SaveFileDialog too, every time you try to step through the “ShowDialog()” method.
This is because of Silverlight’s security model, which doesn’t allow source code to programmatically show a file dialog when an app is running in its default security sandbox (app is not signed with certificate and user hasn’t given consent for it to run in elevated rights mode), unless that code is called from an event handler that handles some user action on the UI (e.g. some button has been clicked by the user).
Obviously, when stepping through with the debugger it loses the user-initiated-action context somehow and considers the debugger as the initiator of the action, thus not allowing the file dialog to be shown when you try to step-through the “ShowDialog()” method of OpenFileDialog or SaveFileDialog.
The only solution I can suggest is to put a breakpoint right after the “ShowDialog()” returns (e.g. at “using” statement in the code below). If you place a breakpoint at any source code row above or at the “ShowDialog” inside the event handler method (“btnLoad_Click” in the code below) it will fail when the debugger tries to go through the “ShowDialog” method, even if you press “Run” after that breakpoint fires to continue.