| Comments

PLEASE READ UPDATE: While the API for checking for updates has changed, the update model *after* that method call to CheckAndDownloadUpdateAsync is the same as described below.  See this note for updates since this article to the Out-of-browser experiences.

Wednesday at MIX09 was a great day.  I was exhausted, but after the keynote I was so high on excitement it was great.  Throughout the day Twitter was buzzing (or is it fizzing?) about all the news around Silverlight 3.  In one conversation around the out-of-browser experiences with Silverlight, I caught a conversation on Twitter about it with questions about the update model.  I jumped in which resulted in this twittersation (sorry, couldn’t resist):

Twitter conversation

So, instead of trying to cram it in 140 characters, I’ll explain here how it works, and take the liberty of using just slightly more than 140 characters.

If you aren’t familiar with the Silverlight Out-of-browser experiences (lovingly referred to as a SLOOB – nod to @bryantlikes), you may want to read my previous post which is a guide to the new features in Silverlight 3 as well as view this video demonstrating the feature.

Detaching the application

The first time your users will view your application it will be in the web context in a page somewhere.  If your application is enabled for out-of-browser (OOB) experiences, then the user can detach the application via a user-initiated action (context menu or some function in your application that calls Detach()).  That process then immediately does a few things:

SLOOB Detach

This action takes the browser (for our example let’s say being served up at http://foo.com/mysloob.xap) and creates an OOB application.  What happens here is the following:

  • The application (XAP) is requested again via the browser
  • The XAP gets stored locally in a low trust location along with metadata which includes the origin URI of the XAP as well as metadata, most importantly for this discussion the ETag information of when it was downloaded (timestamp essentially)

The first OOB launch

Now we are all good.  If we close the application and launch it again from the desktop now we’d initiate a startup of the application:

SLOOB Launch 1

What happens in this instance is basically the application looks at it’s metadata for the origin URI of the XAP and makes a request there with.  It compares the HTTP response data (code and ETag) for comparison.  If the app wasn’t updated, then the app launches and all is well.  In fact inspecting the request it would look something like this for our app:

   1: GET /silverlight/oob/ClientBin/OutOfBrowser.xap HTTP/1.1
   2: If-Modified-Since: Thu, 19 Mar 2009 03:52:35 GMT
   3: User-Agent: Silverlight
   4: Host: timheuer.com
   5: X-P2P-PeerDist: Version=1.0
   6: Accept-Encoding: peerdist
   7:  
   8:  
   9: HTTP/1.1 304 Not Modified
  10: Last-Modified: Thu, 19 Mar 2009 03:52:15 GMT
  11: Accept-Ranges: bytes
  12: ETag: "f2e3a81746a8c91:445"
  13: X-Powered-By: ASP.NET
  14: Date: Thu, 19 Mar 2009 03:55:18 GMT

Notice the HTTP 304 Not Modified response.  No further information is sent and we can see that no content was even delivered.  The app hasn’t changed.  At the API level, Application.Current.ExecutionState is not triggered for a DetachedUpdatesAvailable state change.

Application updated, user launches from desktop

Now let’s update the application and upload to our server.  The next time the user launches the application, the same requests happen:

SLOOB Launch 2

Again, the requests are made sending the metadata information.  In this case though, there is an update.  What happens next is two fold.  Along with the response being sent with a new timestamp/ETag, the request also includes the bits of the updated application.  Looking at the request it would look like:

   1: GET /silverlight/oob/ClientBin/OutOfBrowser.xap HTTP/1.1
   2: If-Modified-Since: Thu, 19 Mar 2009 03:52:35 GMT
   3: User-Agent: Silverlight
   4: Host: timheuer.com
   5: X-P2P-PeerDist: Version=1.0
   6: Accept-Encoding: peerdist
   7:  
   8:  
   9: HTTP/1.1 200 OK
  10: Content-Length: 15557
  11: Content-Type: application/x-silverlight-app
  12: Last-Modified: Thu, 19 Mar 2009 03:56:29 GMT
  13: Accept-Ranges: bytes
  14: ETag: "ce39d0ae46a8c91:445"
  15: X-Powered-By: ASP.NET
  16: Date: Thu, 19 Mar 2009 03:56:45 GMT
  17: <data>

Where “<data>” in the snippet above would actually be the bytes (notice the Content-Length and Content-Type headers) of the updated XAP.  Two things happen now:

  • Application.Current.ExecutionState changes to a DetachedUpdatesAvailable state. 
  • The XAP in the local storage location is updated to the new bits.

Now right now there is no option to decline the updated bits.  If the app is updated, your users will get them.  This is something the team is considering understanding different scenarios.  Also, there is no way to force the user to shutdown the app or prevent them from continuing.  You should build your app in a manner that if an update occurs that perhaps you block the UI until the update is launched.  Re-launching the application (from the local machine) would startup again with the newly downloaded bits and the updated request would look again similar to the first:

   1: GET /silverlight/oob/ClientBin/OutOfBrowser.xap HTTP/1.1
   2: If-Modified-Since: Thu, 19 Mar 2009 03:56:49 GMT
   3: User-Agent: Silverlight
   4: Host: timheuer.com
   5: X-P2P-PeerDist: Version=1.0
   6: Accept-Encoding: peerdist
   7:  
   8:  
   9: HTTP/1.1 304 Not Modified
  10: Last-Modified: Thu, 19 Mar 2009 03:56:29 GMT
  11: Accept-Ranges: bytes
  12: ETag: "ce39d0ae46a8c91:445"
  13: X-Powered-By: ASP.NET
  14: Date: Thu, 19 Mar 2009 03:57:12 GMT

And that’s the basic mechanism of it.  When an application is detached, metadata is stored about that app.  Each launch it does a check against that metadata to see if an update is visible.  If the app is offline, that’s fine, it won’t block the app from launching.  This is very similar to the .NET Framework’s ClickOnce concept in deployment.

Contrast with Adobe AIR Update Framework

Kevin asked me to contrast that with how AIR does it because he felt that “in AIR, very straightforward.”  Now, as you can also see in the initial conversation, I admitted not knowing how AIR worked.  I’m basing the following (and I won’t go deep to get myself into “you’re an idiot” trouble) off of my research in the Adobe AIR developer tutorial on Using the Adobe AIR Update Framework

Now as far as I can tell, first the update framework is not a part of the core AIR runtime and [UPDATE] is avialable in the AIR 1.5 SDK (thanks David for the note) is a separate plugin/module/whatever-term-would-be-appropriate-for-the-runtime for AIR.  Mihai in the tutorial points to needing to download the update framework which apparently is a lab framework (I’m not sure if that means beta, supported or what – if someone knows please comment)?

Once the framework is included the next step is that the developer has to create an update manifest which is described as:

This is a small XML file that keeps information needed by the updater (for example, what version is available, from where to take it, and what info to display). This file sits on your server, and when the application starts up it loads this file to see if any updates are available.

Essentially a file sitting on some location that the app can retrieve (presumably a web server).  The developer then implements an event handler on the AIR WindowApplication.creationComplete event to check for an update.  This includes about 10-15 lines of code to tell the update framework where the manifest file is and to attach to some additional event handlers and code.  When the update is noticed and needed a prompt will occur and AIR has a default UI that would be shown:

Adobe AIR Update Dialog

I like the default UI, it’s informative.  Notice the Release Notes information.  This information comes from the manifest file.  I like that too…good idea.

What it appears to me though is that when the developer has an update the manifest needs to be manually updated or no update events would be triggered.  Perhaps that’s a good thing for granular control over optional events.  I couldn’t find information if you can modify whether “Download Later” was an option or not (thus forcing an update).

Summary

So there you have it.  In Silverlight 3 you have a framework to enable you to auto update your bits.  We’re still in beta so things may change and we know there are questions that you may have on our model (if you have those questions, please leave a comment here).  In AIR you have a framework that doesn’t appear to be a part of the core runtime but that provides the same methods for providing notification to your users.  If I’ve gotten my interpretation of the AIR tutorial wrong, please someone kindly correct me as it wouldn’t have been my intent to do so.

I hope this helps understand the model.  If it didn’t, then perhaps I should have just used 140 characters.


This work is licensed under a Creative Commons Attribution By license.

Please enjoy some of these other recent posts...

Comments