Cook Computing

UrlHelper Extension for Avoiding Incorrect Silverlight XAP File Caching

May 8, 2011 Written by Charles Cook

I wasted some time today trying to work out why a Silverlight web app was not working. Checking the requests from the browser it appeared that the browser was caching the Silverlight XAP file — Chrome and IE9 — and was not checking whether a newer version was available on the server.

This seems to be a common problem and I found a solution on Lars Holm Jensen's blog — Avoid incorrect Silverlight XAP file caching. He writes:

The code below appends the last-write filedate of the Silverlight Application XAP file to the path in the source parametre of the Silverlight object tag.

This will ensure that poorly constructed caching functionality of webbrowsers and proxy servers doesn’t incorrectly use old builds of the XAP file.

However it will still allow these caches to work. Furthermore a check is performed to avoid XAP file path alteration during debugging, this is to allow debugging tools such as Silverlight Spy to continue functioning.

His code is for WebForms and I'm using Razor views with ASP.NET MVC so I wrote a UrlHelper extension for easy usage in a Razor view.

using System;
using System.IO;
using System.Web;
using System.Web.Mvc;

namespace MyApp.Helpers
{
  public static class UrlHelpers
  {
    public static string XapContent(this UrlHelper helper, 
      string xapPath)
    {
      string absPath = helper.Content(xapPath);
      if (!System.Diagnostics.Debugger.IsAttached)
      {
        string xapPath = HttpContext.Current.Server.MapPath(absPath);
        DateTime xapCreationDate = File.GetLastWriteTime(xapPath);
        absPath += ("?ignore=" + xapCreationDate.ToString());
      }
      return absPath;
    }
  }
}

To import the helper class's namespace into the Razor view page, add this line:

@using MyApp.Helpers;

And then use the helper in the Silverlight object element:

<object id="SLP" data="data:application/x-silverlight-2," 
  type="application/x-silverlight-2" width="0" height="0">
    <param name="source" 
      value="@Url.XapContent("~/ClientBin/myappplugin.xap")"/>
    <param name="onError" value="onSilverlightError" />
    <param name="minRuntimeVersion" value="3.0.40818.0" />
    <param name="autoUpgrade" value="false" />
</object>

(Note: I'm not using Silverlight for UI, only for processing some data, hence the zero width and height, and no text to explain how to install Silverlight if it's not installed.)