Silverlight 5 - OOB install/update broken when using anti-cache trick
Asked Answered
E

3

3

I was using the timestamp trick on the Silverlight <object> (see GetLastWriteTime() using answers in How do you force Firefox to not cache or re-download a Silverlight XAP file?) successfully with Silverlight 4.

Using a Silverlight 5 runtime*, the OOB install/auto-update feature now seems broken. I have two issues:

  • when launching in browser, the current install state is always 'not installed' (in code: Application.Current.InstallState == System.Windows.InstallState.NotInstalled is always true)
  • when launching in OOB mode, it's always saying that a new version is available (in code: CheckAndDownloadUpdateAsync() always returns with e.Error == null and e.UpdateAvailable == true).

Has anyone else encountered this, and better yet, has a workaround?


* Precision: currently my app is built using the Silverlight 5 Tools, but is targeting Silverlight 4, and works fine on a Silverlight 4 Developer Runtime. The problem occurs on (at least) my dev machine using the Silverlight 5 Developer Runtime.


Update: I've checked with Fiddler what happens on my dev box. When the update process is invoked, I see:

GET /ClientBin/Client.xap?timestamp=23%2f01%2f2012+17%3a42%3a14 HTTP/1.1
If-Modified-Since: Tue, 24 Jan 2012 09:10:07 GMT

That's fine for me, except that the server (Server: ASP.NET Development Server/10.0.0.0, X-AspNet-Version: 4.0.30319) returns a new version, with the following cache headers:

HTTP/1.1 200 OK
Cache-Control: private
Date: Tue, 24 Jan 2012 09:11:28 GMT

Each time I run the app, the check request has the right date (the one previously returned by the server), and each time, the server says it has a new version, with the current date. I will try to tweak the server config.

Update2: I had a cache control directive in my Web.config file, but removing it only solved half the problem. Now the in browser app detects that the OOB install is ok, but the update cycle continues, with the same Fiddler trace.

Update3: The problem is definitely related to the debug web server. The same application deployed to a proper IIS with the same Web.config doesn't have this issue. But this is still annoying, as it considerably slows down my OOB debug process.

Update4: In fact, the problem is still present even on my main IIS deployment, and has happened on other servers too (and using PHP to generate the timestamp instead of ASP.NET). So any help is appreciated.

Update5: As requested, here is my code, fairly straightforward:

private void CheckAndDownloadUpdateCompleted(object sender, System.Windows.CheckAndDownloadUpdateCompletedEventArgs e)
{
    if (e.Error != null)
    {
        if (e.Error is PlatformNotSupportedException)
        {
            UpdateType = UpdateTypes.PlatformUpdate;
            //(...)
            return;
        }
        else if (e.Error is SecurityException)
        {
            UpdateType = UpdateTypes.ElevationRequired;
            //(...)
            return;
        }
        else
        {
            // Error handling code
            //(...)
        }
    }
    else if (e.UpdateAvailable)
    {
        UpdateType = UpdateTypes.Available;
        //(...)
        return;
    }

    UpdateType = UpdateTypes.NoUpdate;

    //(...)
}

UpdateType is an enum type property that allow me to pick the right localized string somewhere else.

Update6: The various //(...) parts are (indirectly) changing the view of the application, UpdateType is not.

Erythritol answered 23/1, 2012 at 16:25 Comment(6)
I've experienced a similar issue when using Mono's xsp web server and reported a bug here: bugzilla.novell.com/show_bug.cgi?id=649789. How are you testing that an update is available? I am not sure but maybe e.UpdateAvailable is indicating that a silverlight runtime update is available instead of just a program update? When I use IIS this is not an issue because IIS is using its built-in cache control. How are you installing the silverlight application OOB?Clementius
I've got a button in my app that's only visible if the application is not yet installed. This is broken (application is reported as not installed when in fact it is).Erythritol
Sometimes I also use the right click => Install feature, same results.Erythritol
And yes, I'm checking the 3 different kinds of updates. I've seen it work fine when I switched to SL5 for the app on a PC with SL4 installed.Erythritol
I just wanted to confirm we had this working fine in SL4 and see the same issue as you in SL5 - it always thinks there is an update available; seeing the same response from the server as you (using timestamp).Expecting
Could I at least have an explanation for the downvote? This question is useful to some people, I've added many details to extract the issue, ...Erythritol
K
1

I suspect this has something to do with the builtin Cassini / Visual Studio Development server and SL5 not playing nicely together for some reason.

I'm also using the anti-cache trick you mentioned and I was experiencing the same behavior of Application.Current.InstallState always reporting NotInstalled as well as CheckAndDownloadUpdateAsync() always reporting e.UpdateAvailable = true.

So I changed my web project configuration to use IIS Express instead of the the builtin Visual Studio Development server and re-installed the Silverlight app to the desktop. Finally, everything started working as expected. In order words Application.Current.InstallState = Installed and CheckAndDownloadUpdateAsync() is reporting e.UpdatedAvailable = false.

Update:

Sorry, didn't see that you're experiencing this as well on live IIS deployments.

Update 2:

My anti-cache HTML as requested:

<div id="silverlightControlHost" align="center" style="height:100%">
    <object data="data:application/x-silverlight-2," type="application/x-silverlight2" width="100%" height="100%">
      <%
          string source = @"~/ClientBin/EskomVDT.SL.xap";
          string param;

          if(System.Diagnostics.Debugger.IsAttached) {
              param = "<param name=\"source\" value=\"" + VirtualPathUtility.ToAbsolute(source) + "\" />";                                   
          }
          else {
              string xapPath = HttpContext.Current.Server.MapPath(source);
              DateTime xapCreationDate = System.IO.File.GetLastWriteTime(xapPath);

              param = "<param name=\"source\" value=\"" + VirtualPathUtility.ToAbsolute(source) + "?ignore=" + xapCreationDate.ToString("yyyy-MM-dd-hh-mm-ss") + "\" />";
          }

          Response.Write(param);
      %>
      <param name="onError" value="onSilverlightError" />
      <param name="background" value="white" />
      <param name="minRuntimeVersion" value="5.0.61118.0" />
      <param name="autoUpgrade" value="true" />
      <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.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>
Krafftebing answered 25/4, 2012 at 12:17 Comment(4)
Well, for the installation detection part, you're right, the embedded server was messing up worse than IIS (or an unknown PHP provider on a client website). But my real problem is the update detection, which sadly persists.Erythritol
As this was the only answer with something like a solution, I awarded the bounty, although it doesn't solve my problem.Erythritol
Could you show your own anti-cache code? Or at least the resulting HTML?Erythritol
I had this same error using SL5 and VS 2010, though I was not using the anti-cache trick. Switching from Visual Studio Development Server (Cassini) fixed the problem for me, and now e.UpdateAvailable has the correct value instead of being true all the time.Harkness
P
1

I have the same issue when run as OOB from Visual Studio

Regarding running from IIS remotely, I noticed that I had to edit the caching policy I had added to web.config - keeping that would always show the update/download progress logo (but would download faster than when a new version was available, only partial download maybe, but annoying to see the download progress even for a while every time)

I had to remove (comment out) the part that was trying to cache .xap till changed

<caching>
  <profiles>
    <add extension=".xap" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/>
  </profiles>
</caching>
Plauen answered 22/7, 2013 at 10:14 Comment(0)
C
0

I recommend not using the DateTime approach.
Instead, append the version number to the xap url.

Edit
Sorry, just noticed you're using the LastWriteTime, which should be fine.

Try using fiddler to view the network traffic when the xap is served through IIS.

Also, show us your code that does the OOB installed check.

Edit 2

What is the default value of UpdateType? Maybe the code that checks the value of UpdateType might have run before CheckAndDownloadUpdateCompleted is called.

In regards to Application.Current.InstallState, hook into the event App.Current.InstallStateChanged.
I'm thinking maybe the default value of Application.Current.InstallState is System.Windows.InstallState.NotInstalled until the silverlight runtime has finished checking the install state, at which case it then fires the InstallStateChanged event.

When your page is loaded in your web browser, check its html source, maybe the last file write time is getting updated unexpectedly.

Clementius answered 25/2, 2012 at 0:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.