Working on the MusicStore project for the next DotNetMarche workshop I had the following scenario:

- A Web Service used to provide some data and images to the application.

- A Silverlight application (on a different website) that consumes the data and the images binding some absolute urls to Silverlight’s image controls.

here Image contains an absolute uri like: "http://localhost.:50671/Images/1.jpg"
 
<Image Source="{Binding Image}" Width="40" Height="40"/>

The whole thing is pretty simple and easy to setup and I expected it work at the first run...and I was very surprised when it did not. I did these things often in the past and I am pretty sure that downloading an image is an allowed operation (even without a client access policy).

No errors were reported, nothing on my logs, no binding errors. So I started investigate and I opened up Fiddler to track what’s happening on the wire, I modified the addresses of any request I wanted to analyze to add a ‘.’ after the localhost keyword (otherwise Fiddler won’t track them and here are the results:

AG_E_NETWORK_ERROR1

You can see the request to the policy file and the request at the web service to gather some data, but...nothing about the images that should be downloaded after...something strange is going on, further investigations are needed, the binding infrastructure is eating my error is some way.

Now, when you bind an image to a URI under the hood the engine automatically creates a BitmapImage object that is responsible for loading the image and passing the data to the control. The BitmapImage have an event - ImageFailed - that you can subscribe to get a notification of a failure loading the image. We can just write our own BitmapImageConverter and use it in the binding to get some more info:

/// <summary>
/// Use this converter for converting a URI to a BitmapImage object
/// Example:
/// Text="{Binding Path=Image, Converter={StaticResource BitmapImageConverter}"
/// </summary>
public class BitmapImageConverter : IValueConverter
{
    #region IValueConverter Members
 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            BitmapImage convert = new BitmapImage(new Uri(value.ToString(), UriKind.Absolute));
            convert.ImageFailed += (sender, e) =>
                                            {
                                                System.Diagnostics.Debug.WriteLine(e.ErrorException.ToString());
                                            };
            return convert;
        }
        return null;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
 
    #endregion
}

And we use it like:

   1: In the resources section:
   2:  
   3: <converters:BitmapImageConverter x:Key="UrlToBitmap" />
   4:  
   5: The binding is like:
   6:  
   7: <Image Source="{Binding Path=Image, Converter={StaticResource UrlToBitmap}}" Width="40" Height="40"/>

We can now set a breakpoint on the Debug.WriteLine() call and look at the exception:

AG_E_NETWORK_ERROR2 

AG_E_NETWORK_ERROR!!! this is a pretty generic error and you usually you this it (dealing with media elements like images, videos, and such) when Silverlight cannot find or understand the resource you trying to load, no more details are given here; but I couldn’t even see the request for the resource being made, something very bad is going on here.

I spent some time doing other esoteric investigations when I saw HOW the application was requested in the browser and started hammering my head on the wall for having lost time in a stupid way!

AG_E_NETWORK_ERROR3

You can see it: “file://”, when I created the project I chose to NOT create an Asp.Net web project to host the Silverlight application and let Visual Studio create a default test page for me; BUT it open this page direcly pointing to the page on the file system so the request scheme is ‘file://’.

If you take a look at the URL Access Restrictions in Silverlight (and if you are a Silverlight developer you should know at least some of them) you see that cross-scheme calls are not allowed for images! I opened the application with ‘file://’ scheme, but was requesting something with ‘http://’ scheme.

The solution was to create the ‘damned’ Asp.Net web project to host the Silverlight application and start that instead, everything started to work fine as it should!

To be honest getting an AG_E_NETWORK_ERROR is quite misleading here, something that reported a SECURITY error or failure would have been more suited to the situation and could lead to the problem resolution faster.

Related Content