Michael Crump bio photo

Michael Crump

Works at Microsoft on Azure

Twitter Google+ LinkedIn Instagram Github Youtube

If you work with Silverlight daily then you have run into this problem. Your XAP file has been cached in your browser and you have to empty your browser cache to resolve it. If your using Google Chrome then you typically do the following:

Go to Options –> Clear Browsing History –> Empty the Cache and finally click Clear Browsing data.

SNAGHTML1f6c763d

As you can see this is a lot of unnecessary steps. It is even worse when you have a customer that says “I can’t see the new features you just implemented!” and you realize it’s a cached xap problem.  I have been struggling with a way to prevent my XAP file from caching inside of a browser for a while now and decided to implement the following solution.

  1. If the Visual Studio Debugger is attached then add a unique query string to the source param to force the XAP file to be refreshed.
  2. If the Visual Studio Debugger is not attached then add the source param as Visual Studio generates it. This is also in case I forget to remove the above code in my production environment.
  3. I want the ASP.NET code to be inline with my .ASPX page. (I do not want a separate code behind .cs page or .vb page attached to the .aspx page.)

Below is an example of the hosting code generated when you create a new Silverlight project. As a quick refresher the hard coded param name = “source” specifies the location of your XAP file. 

<form id="form1" runat="server" style="height:100%">  <div id="silverlightControlHost">      <object data="data:application/x-silverlight-2" type="application/x-silverlight-2" width="100%" height="100%">        <param name="source" value="ClientBin/SilverlightApplication2.xap"/>        <param name="onError" value="onSilverlightError" />        <param name="background" value="white" />        <param name="minRuntimeVersion" value="4.0.50826.0" />        <param name="autoUpgrade" value="true" />        <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">             <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>        </a>      </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>  </form>

We are going to use a little bit of inline ASP.NET to generate the param name = source dynamically to prevent the XAP file from caching. Lets look at the completed solution:

<form id="form1" runat="server" style="height:100%">     <div id="silverlightControlHost">         <object data="data:application/x-silverlight-2" type="application/x-silverlight-2" width="100%" height="100%">         <%             string strSourceFile = @"ClientBin/SilverlightApplication2.xap";             string param;                 if (System.Diagnostics.Debugger.IsAttached)                 //Debugger Attached - Refresh the XAP file.                 param = "<param name=\"source\" value=\"" + strSourceFile + "?" + DateTime.Now.Ticks + "\" />";             else             {                 //Production Mode                  param = "<param name=\"source\" value=\"" + strSourceFile + "\" />";             }             Response.Write(param);          %>            <param name="onError" value="onSilverlightError" />           <param name="background" value="white" />           <param name="minRuntimeVersion" value="4.0.50826.0" />           <param name="autoUpgrade" value="true" />           <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">                <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>           </a>         </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>  </form>

We add the location to our XAP file to strSourceFile and if the debugger is attached then it will append DateTime.Now.Ticks to the XAP file source and force the browser to download the .XAP. If you view the page source of your Silverlight Application then you can verify it worked properly by looking at the param name = “source” tag as shown below.

image

<param name="source" value="ClientBin/SilverlightApplication2.xap?634299001187160148" /> 

If the debugger is not attached then it will use the standard source tag as shown below.

<param name="source" value="ClientBin/SilverlightApplication2.xap"/>

At this point you may be asking How do I prevent my XAP file from being cached on my production app? Well you have two easy options:

1) I really don’t recommend this approach but you can force the XAP to be refreshed everytime with the following code snippet. 

<param name="source" value="ClientBin/SilverlightApplication2.xap?<%=Guid.NewGuid().ToString() %>"/>

NOTE: You could also substitute the “Guid.NewGuid().ToString() for anything that create a random field. (I used DateTime.Now.Ticks earlier).

2) Another solution that I like even better involves checking the XAP Creation Date and appending it to the param name = source. This method was described by Lars Holm Jenson.

<%      string strSourceFile = @"ClientBin/SilverlightApplication2.xap";      string param;      if (System.Diagnostics.Debugger.IsAttached)          param = "<param name=\"source\" value=\"" + strSourceFile + "\" />";      else      {          string xappath = HttpContext.Current.Server.MapPath(@"") + @"\" + strSourceFile;          DateTime xapCreationDate = System.IO.File.GetLastWriteTime(xappath);          param = "<param name=\"source\" value=\"" + strSourceFile + "?ignore="                  + xapCreationDate.ToString() + "\" />";      }      Response.Write(param);  %>