How do you force Firefox to not cache or re-download a Silverlight XAP file?

SilverlightFirefox

Silverlight Problem Overview


When working with Silverlight, I've noticed that Firefox will cache the XAP file, so if I do an update, a user may be stuck using an outdated version. Is there a way to force the browser to either re-download the XAP file every time, or maybe only force it to after an update has been published? Or is there a setting in the Silverlight config that stops the browser from caching the XAP file altogether?

Thanks, jeff

Silverlight Solutions


Solution 1 - Silverlight

The query string works perfectly, but I wouldn't use DateTime.Now, because it forces the user to re-download the app every time. Instead, we use the following:

protected void Page_Load(object sender, EventArgs e)
{
    var versionNumber = Assembly.GetExecutingAssembly().GetName().Version.ToString();
    this.myApp.Source += "?" + versionNumber;
}

This way all you have to do is increment the version number in the AssemblyInfo.cs file.

Solution 2 - Silverlight

Simplest way:

<param name="source" value="ClientBin/App.xap?<%= DateTime.Now.Ticks %>" />

Solution 3 - Silverlight

This is what I do in php. You read the date/time of the xap file, and append it as a parameter to the download link. In that way the browser sees new file versions as new links, and therefore not in its cache.

<?php $fdate = date("dHis",filemtime("MyApp.xap")) ?>

<param name="source" value="MyApp.xap?=<?php echo $fdate ?>"/>

Simple and it works. Also, browsers continue to cache correctly when there are no updates to download.

Solution 4 - Silverlight

You might find the Caching Tutorial for Web Authors and Webmasters helpful. This document discusses the different caches through which the client and server interact (browser, proxy, gateway) and how caching can be controlled.

Solution 5 - Silverlight

For me, the best answer is from Chris Cairns. I've just adapted it a little, calling ToString and GetHashCode, generating an ID to the timestamp:

<param name="source" value="ClientBin/App.xap?<%= System.IO.File.GetLastWriteTime(Server.MapPath("ClientBin/App.xap")).ToString().GetHashCode()%>" />

Works just fine!

Solution 6 - Silverlight

You could send HTTP headers to prevent it from caching:

Cache-control: no-cache
Pragma: no-cache

How you do this depends on the web server you're using.

Solution 7 - Silverlight

Another solution would be to append the version of the XAP file rather than a timestamp. The timestamp would change every time (might as well turn off caching). To get it to only change when the XAP has been updated would be to take some info from the XAP file. Am still looking into what I could use, perhaps the last modified datestamp of the XAP file?

Solution 8 - Silverlight

Adding the timestamp for the XAP worked for me (I'm adding the SL control in javascript but this could just as easily be done inline):

var appTimestamp = '<%= System.IO.File.GetLastWriteTime(Server.MapPath("ClientBin/MyApp.xap")) %>';
var source = 'ClientBin/MyApp.xap?appTimestamp=' + appTimestamp;

Solution 9 - Silverlight

This tested and working:

Put this:

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

Instead of this:

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

Solution 10 - Silverlight

I'm getting this to work by a combination of the suggestions above:

  1. Set meta tag cache-control/pragma http-equiv attributes to 'No-Cache'

  2. Use an ASP.NET page to host the silverlight control (as opposed to an html page)

  3. Set the Source property of the ASP.NET Silverlight control in the code behind, appending a time stamp to the .xap url e.g.

    Silverlight1.Source = "ClientBin/MyApplication.xap?" + DateTime.Now.ToString("dd-MM-yy-HH:mm:ss");

Solution 11 - Silverlight

You can append the source url in the object tag with the last-write date of the XAP file. Check the code at my blog.

Solution 12 - Silverlight

We are also in the same situation wherein we want to control when the .XAP file gets downloaded to the browser.

An approach that you might want to take a look at is to use the Silverlight Isolated Storage as a "cache" to store your .XAP files.

Check out this blog: IsolatedStorage as a Silverlight object cache

Solution 13 - Silverlight

A super simple idea: just add a fake query string to the url.

<param name="source" value="app.xap?r12345"/>

Most servers should ignore it and server the file normally--depends on your server. If you get really clever, you could make the hosting page dynamic and automatically append a tick-count or date-time string to the query string. This ensures that you get caching when you want it, but force a download when there's a change.

Ideally, your server should do this for you. But if not...

Solution 14 - Silverlight

I had this issue so now when I start a new application I set the assembly version to 0.0.0.1 and just update it by one on every deployment, seems to have solved it for me. Then just set it back to 1.0.0.0 on release.

Solution 15 - Silverlight

So far, the only solution that I have found, once the problem occurs, is to clear the Firefox cache.

A better solution would be much better.

Solution 16 - Silverlight

I use this solution

<object id="Xaml1" data="data:application/x-silverlight-2," type="application/x-silverlight-2"
width="100%" height="100%">
<%––<param name="source" value="ClientBin/SilverlightApp.xap"/>––%>
<%
string orgSourceValue = @"ClientBin/SilverlightApp.xap";
string param;
if (System.Diagnostics.Debugger.IsAttached)
param = "<param name=\"source\" value=\"" + orgSourceValue + "\" />";
else
{
string xappath = HttpContext.Current.Server.MapPath(@"") + @"\" + orgSourceValue;
DateTime xapCreationDate = System.IO.File.GetLastWriteTime(xappath);
param = "<param name=\"source\" value=\"" + orgSourceValue + "?ignore="
+ xapCreationDate.ToString() + "\" />";
}
Response.Write(param);
%>
<param name="onError" value="onSilverlightError" 

Solution 17 - Silverlight

The query string idea doesn't work for me in Silverlight 4. The server seems to cache the darned xap (though not the aspx file). The solution that does work in SL4 is to go to properties on your Silverlight project, go to Assembly info and put in a version.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYttriumView Question on Stackoverflow
Solution 1 - SilverlightRomainView Answer on Stackoverflow
Solution 2 - SilverlightAndy MehalickView Answer on Stackoverflow
Solution 3 - SilverlightFlappySocksView Answer on Stackoverflow
Solution 4 - Silverlightconverter42View Answer on Stackoverflow
Solution 5 - SilverlightJwJosefyView Answer on Stackoverflow
Solution 6 - SilverlightJarett MillardView Answer on Stackoverflow
Solution 7 - SilverlightStephen PriceView Answer on Stackoverflow
Solution 8 - SilverlightChris CairnsView Answer on Stackoverflow
Solution 9 - SilverlightAlexanderiusView Answer on Stackoverflow
Solution 10 - SilverlightPhil SteelView Answer on Stackoverflow
Solution 11 - SilverlightLars Holm JensenView Answer on Stackoverflow
Solution 12 - SilverlightptioView Answer on Stackoverflow
Solution 13 - SilverlightKevin MooreView Answer on Stackoverflow
Solution 14 - SilverlightDavid CaseyView Answer on Stackoverflow
Solution 15 - SilverlightTimothy Lee RussellView Answer on Stackoverflow
Solution 16 - SilverlightVladimir DorokhovView Answer on Stackoverflow
Solution 17 - SilverlightChris BordemanView Answer on Stackoverflow