Friday, May 14, 2010

WebClient and DeploymentCatalog gotchas in Silverlight OOB

This is a quick post to share a gotcha I found that may be impacting others.

I am in the process of building a large composable application for a customer using Silverlight 4 and the Managed Extensibility Framework (MEF). The application has a framework that supports multiple line of business applications that are dynamically loaded and registered to the main application.

This application works both in browser and out-of-browser and even in offline mode. The DeploymentCatalog in MEF works with the web client stack underneath the hood, so it functions the same way as if you tried to request the files yourself and then pull them down. If online, it will request from the web, otherwise it will look to cache. If the cache is empty, you're stuck.

The first caveat with working out of browser is that relative urls no longer work. They are relative to your install base so they will not find the XAP. There are a few ways to resolve this, but the easiest I've found is to sense when running online (i.e. the first time it is launched) and save the URI to IsolatedStorageSettings. Then, in offline mode, you can pull it out and reconstruct the URI back to the place the host XAP was located, and specify a fully qualified URI:

if (Current.IsRunningOutOfBrowser)
    Source = IsolatedStorageSettings.ApplicationSettings[SOURCEURI] as Uri;
    var src = Current.Host.Source.ToString();
    src = src.Substring(0, src.LastIndexOf('/')+1);
    Source = new Uri(src);
    IsolatedStorageSettings.ApplicationSettings[SOURCEURI] = Source;

Now you can easily make a full URI like this:

var uri = new Uri(Source, "local.xap");

After that point it is mostly business as usual, unless you run into a problem like I did. My application was working perfectly in the browser, but in OOB mode it would not load. I started debugging and found that all of my WebClient and DeploymentCatalog downloads would fire ... but then nothing would happen. They'd never return, not even with an error.

This was very puzzling to me and I researched it far and wide and could not find a resolution. I made a sample side project as a proof of concept and everything worked fine. What was different?

I actually reached out to my team for help when it hit me ... something a little "different" I was doing.

The App.cs typically sets the RootVisual of your application. You might create a new control and set it or use composition to import it. Because I had multiple modules to load, I wanted to delay setting the root visual until everything was loaded. So, I created a special loader class to do this, and held off on assigning the root visual until composition was complete.

It turns out this was the culprit. While it worked fine in the web browser, something in OOB was expecting the root visual to be set. When I set it to an empty grid, everything suddenly worked fine. So, I put the empty grid in place and then add the composed control as a child of the grid when composition finishes.

We were going to add this anyway (to provide a nice status to the user as the parts were being initialized) but I never suspected it would kill my ability to do anything on the network. If you have experienced similar quirkiness in your applications, this may be one place to look.

A colleague believes it may be due to the fact that WebClient and DeploymentCatalog (via web client) both return via Dispatcher, and with no root visual, there may be no dispatcher to latch to ... sounds plausible to me.

Also wanted to share that a case study for an important Silverlight project was officially released by Microsoft:

Vancouver Winter Olympics Case Featuring Wintellect's Works with Microsoft and NBC

Learn about Wintellect's work with Microsoft and NBC/CTV to support real time video for the 2010 Vancouver Winter Olympics video site using Smooth Streaming and Silverlight. Read the recently released case study and learn about the massive effort across multiple partners to pull together the on-line solution for streaming HD videos, both live and on demand for the Vancouver Winter Olympics. Get an inside view of Wintellect's contribution to making this project a success with coverage of 360 events, 4.4 million hours of video, and much more!

Here is the link: Winter Olympics Case Study

Jeremy Likness