This article is compatible with the latest version of Silverlight.
This is the first in a 3-part series of articles about caching & Silverlight.
You can download the source code here.
A lot can be written about this subject, and because of that, quite a few misunderstandings about Silverlight and caching exist.
Let’s start with a general definition of caching: this is what Wikipedia has to say about this technique:
In computer science, a cache is a component that improves performance by transparently storing data such that future requests for that data can be served faster. ... (en.wikipedia.org/wiki/Caching)
Well, that sure opens up a lot of possible places to cache, in and outside of your Silverlight application. Can you cache the complete Silverlight application? What’s this assembly caching you keep on reading about? How do you go about keeping your data on the client when navigating to different parts of you application, instead of refetching it all the time? Can you leverage the Isolated Storage for caching, and is it possible to persist data in between different application sessions? Is it possible to share cached items between different Silverlight applications? And what about the server-side: can I minimize database hits when launching queries from my Silverlight application?
If you’ve ever asked yourself one (or more) of these questions, this article series is for you. As you might notice when seeing them in the same paragraph, these questions are about different ways of caching, and they all apply to different scenarios.
In the first part of this series, I’d like to talk about the caching of your Silverlight application itself and Assembly Caching – almost no code is required for this.
XAP Caching
Every Silverlight application consists of one or more XAP files. Smaller applications typically consist of one XAP, but larger applications might benefit from dividing your application into different application modules, compiling into different XAP-files which are loaded on demand. When a user first navigates to a page hosting a Silverlight application, the full XAP has to be downloaded to the client. As an XAP typically contains a bunch of referenced assemblies, your XAML files, compiled code and everything else you’ve included as embedded resources in your Silverlight project, these files have a tendency to get quite big. Therefore, being able to cache these files will reduce the time a user has to wait to access your application.
Luckily, this is done by default with the help of your browser cache. Once a Silverlight application has been downloaded to the client, it will automatically be cached in the browsers’ temporary files. The next time a user accesses your Silverlight application, the XAP will be loaded from the browser cache (well, as long as it hasn’t been cleared of course – browser caching is controlled by the client and/or browser, we cannot assume anything in this case) instead of from the server.
However, as a developer, this might pose some problems. Imagine the following scenario: a user has opened your Silverlight application, so it’s in the browser cache. In the meantime, you find a bug in your application, solve it, and roll out a new version of your app. Next time that user accesses the hosting web page, you of course want him to get the new version of your application. However, as the previous version is in his browser cache, he will get that version instead of the new one… Luckily, you can control when an XAP should expire (as you can with every file) through IIS.
Open up Internet Information Services Manager, and navigate (in Content View) to the website you’re hosting your Silverlight application on. Select the XAP, open up the Features view, select HTTP Response Headers, and click on Set Common Headers in the Actions pane. Choose “Immediately” in the Expire Web Content popup, and close the popup again.
After you’ve done this, a new version of the XAP will be downloaded to the client when he accesses the hosting web page, even if he already has a version of your application in his browser cache.
As you can see, you also have the option to let the file expire at regular intervals. This might come in handy in a development/test environment: if you’re running a server which receives a new nightly build of your application so the test team can work on the new version the day after, it might be a good idea to use one of these options to ensure the testers will always test on the latest version.
XAP Caching in an Out of Browser scenario?
If you’re designing an Out of Browser application, you might notice your XAP doesn’t get updated automatically – even if you’ve made sure it’s expired, and a new version should be downloaded. This is because in an Out of Browser scenario, you need to download the new version yourself. This is typically done in the application startup method:
private void Application_Startup(object sender, StartupEventArgs e)
{
// OOB new version check
this.CheckAndDownloadUpdateCompleted += (send, args) =>
{
if (args.UpdateAvailable)
{
MessageBox.Show("A new version of the application is downloaded, please restart the application to launch the new version.");
}
};
this.CheckAndDownloadUpdateAsync();
this.RootVisual = new MainPage();
}
This code will ensure your Out of Browser application is updated as well.
Assembly Caching
In Silverlight 3, a new feature was introduced: assembly caching. A lot of people don’t seem to know what this feature actually does, and therefore hesitate to use it. Assembly caching makes sure external assemblies are not packaged in the XAP file, making the XAP itself significantly smaller. Whenever a user accesses your application, the external assemblies will be downloaded from their respective locations: this can be the Microsoft site, a vendor-specific location (if you’re using a 3rd party control library, for example), or even your own central assembly repository. In a default scenario, the assemblies themselves are copied to the ClientBin directory, so they’re always available.
You might wonder: what’s there to gain from this? In the end, the assemblies must be downloaded anyway, so the total download size / time is about the same, right? This is where your browser cache comes into play: as with the XAP file itself, the external assemblies are cached by your browser. This means that if the assembly is already in your browser cache, it does not have to be downloaded again. If you combine this knowledge with content expiration, you can now image a scenario where you roll out a new version of your Silverlight application, expire the XAP immediately (so a new version is delivered to the client), but leave the unchanged external assemblies alone, so they don’t expire. Now, when a client navigates to your application, the new version of the XAP will be downloaded, but the external (unchanged) assemblies will come from the browser cache.
To enable assembly caching, navigate to the project properties of your Silverlight application, and check Reduce XAP size by using application library caching:
If you rebuild your application, you will notice your ClientBin directory now contains zip-files (one for each external assembly you referenced). For example purposes, I’ve added a reference to System.Windows.Controls.Toolkit to my Silverlight application, resulting in 2 zip files: System.Windows.Controls.Toolkit.zip and System.Windows.Controls.zip (which is used by the Toolkit assembly):
Needless to say, as far as strategies to reduce your XAP size (and thus: decrease download time) are concerned, this feature should not be overlooked.
One final word of notice: this feature cannot be combined with an Out of Browser Silverlight application.
Conclusion
This concludes the first part of this 3-part series on caching, in which we’ve learned about how to leverage and control the browser cache, and how to enable Assembly Caching in your Silverlight application. In the next part, we’ll have a look at using the Isolated Storage to enable various caching scenarios.
About the author
Kevin Dockx lives in Belgium and works at RealDolmen, one of Belgium's biggest ICT companies, where he is a technical specialist/project leader on .NET web applications, mainly Silverlight, and a solution manager for Rich Applications (Silverlight, Windows Phone 7 Series, WPF, Surface). His main focus lies on all things Silverlight, but he still keeps an eye on the new developments concerning other products from the Microsoft .NET (Web) Stack. As a Silverlight enthusiast, he's a regular speaker on various national and international events, like Microsoft DevDays in The Netherlands, Microsoft Techdays in Portugal or on BESUG events (the Belgian Silverlight User Group). Next to that, he also authored a best-selling Silverlight book, Packt Publishing's Silverlight 4 Data and Services Cookbook, together with Gill Cleeren. His blog, which contains various tidbits on Silverlight, .NET, and the occasional rambling, can be found at http://blog.kevindockx.com/.