以编程方式使 Silverlight XAP 文件从浏览器缓存中过期

Posted

技术标签:

【中文标题】以编程方式使 Silverlight XAP 文件从浏览器缓存中过期【英文标题】:Making the Silverlight XAP file expire from browser cache programmatically 【发布时间】:2011-01-17 22:09:55 【问题描述】:

如何防止 Web 浏览器缓存 Silverlight XAP 文件?

我想这样做的原因是在开发过程中我不想手动清除浏览器缓存,我正在寻找一种程序化的方法服务器端。

【问题讨论】:

【参考方案1】:

使用 IIS 管理添加自定义标头 Cache-Control,其值为 no-cache。这将导致浏览器在使用之前检查 XAP 的任何缓存版本是否为最新版本。

【讨论】:

这是一个很好的回应,比很多其他人都好(我已经看到你在这里多次给出这个答案。)我是网络开发的新手,但是在阅读了下面的教程之后......我可以看到这正是 XAP 缓存所需要的。这确实是一个很好的解决方案。 Tutorial on Caching 这不会强制浏览器从不缓存 XAP 吗?还是确保它只在 XAP 相同时才缓存? 有没有办法通过 Web.Config 做到这一点?我的项目托管在我无法访问 IIS 管理的服务器中。【参考方案2】:

html 页面上的元素中为 XAP 的 URL 添加查询参数:

clientBin/MyApp.xap?rev=1 clientBin/MyApp.xap?rev=2

它将被忽略并破坏缓存。 在IE8中,有一些缓存管理工具: 打开开发者工具:

尝试缓存...始终从服务器刷新 尝试缓存...清除此域的浏览器缓存...

【讨论】:

当引用静态资源的 URL 是动态生成时,对静态资源的修订号会非常有效,因此您可以添加这些引用。然而,它需要相当多的自定义基础设施才能动态地实现这一点,并且开发人员必须记住手动升级版本号。如果资源在多个地方使用,情况会变得更糟。由于单个客户端不太可能以高频率请求 XAP,因此更需要偶尔的“未修改”响应。【参考方案3】:

here 提出的解决方案有点类似于 Michael 的解决方案,但它是自动的,并保证客户总是会得到一个新版本。根据您的情况,这可能效率低下。

由于 Lars 在他的 comments that he is not on Stack Overflow 中说,我在此复制回复。

<object id="Xaml1" data="data:application/x-silverlight-2,
    "type="application/x-silverlight-2"  >

  <%––<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);     
  %>

  ....

</object>

【讨论】:

我试了一下这个方法,虽然我可以调试并看到正确构建的“参数”,但 Response.Write 在我的示例中写入 标记的开头上方。关于如何解决这个问题的任何想法? 呃……这真的很奇怪。也许你可以 Response.Write 包括参数在内的整个对象标签? 确实很奇怪,我想把全部写出来,我做到了。似乎我们正在使用一个框架,它不能处理它们在 aspx/Response 流中的位置的 response.writes。将与他们联系,看看他们是否可以为我指明写作方向。感谢您的回复 不适用于由 shell XAP 下载模块 XAP 的 PRISM 应用程序。【参考方案4】:

创建用于处理 *.xap 文件的自定义 http 处理程序,然后在处理程序中设置缓存选项。

这样的……

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

public class FileCacheHandler : IHttpHandler

    public virtual void ProcessRequest(HttpContext context)
    
        if (File.Exists(context.Request.PhysicalPath))
        
            DateTime lastWriteTime = File.GetLastWriteTime(filePath);
            DateTime? modifiedSinceHeader = GetModifiedSinceHeader(context.Request);

            if (modifiedSinceHeader == null || lastWriteTime > modifiedSinceHeader)
            
                context.Response.AddFileDependency(filePath);
                context.Response.Cache.SetLastModifiedFromFileDependencies();
                context.Response.Cache.SetCacheability(HttpCacheability.Public);
                context.Response.TransmitFile(filePath);
                context.Response.StatusCode = 200;
                context.Response.ContentType = "application/x-silverlight-app";
                context.Response.OutputStream.Flush();
            
            else
            
                context.Response.StatusCode = 304;
            
        
    

    public DateTime? GetModifiedSinceHeader(HttpRequest request)
    
        string modifiedSinceHeader = request.Headers["If-Modified-Since"];
        DateTime modifiedSince;
        if (string.IsNullOrEmpty(modifiedSinceHeader)
          || modifiedSinceHeader.Length == 0
          || !DateTime.TryParse(modifiedSinceHeader, out modifiedSince))
            return null;

        return modifiedSince;
    

【讨论】:

【参考方案5】:

我在xap文件的路径中添加了一个query parm,这样我就可以通过Versioning来管理它。

Default.aspx 代码:

<param
   name="source"
   value="ClientBin/MySilverLightApp.xap?xapid<%=XapID %>" />

Default.aspx.cs 代码:

protected string XapID

    get
    
        Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

        if (System.Diagnostics.Debugger.IsAttached)
            Response.Write(string.Format("Build: 0.1.2.3", v.Major.ToString(), v.Minor.ToString(), v.Build.ToString(), v.Revision.ToString()));
        return string.Format("0.1.2.3", v.Major.ToString(), v.Minor.ToString(), v.Build.ToString(), v.Revision.ToString()
    

【讨论】:

【参考方案6】:

以上所有示例都依赖于浏览器不缓存包含新技巧 xap 名称的 HTML.... 所以您只需将问题转移到其他问题上即可。 而且它们也非常复杂......

但是对于调试的情况,至少,在javascript中写标签是很容易的,这样每次使用html页面时名称都会改变,不管它是否被浏览器缓存!
<script type="text/javascript">
   document.write('<object blah blah >');
   document.write('<param name="Source" value="myapp.xap?'
               + new Date().getTime()+'">');
   document.write('</object>'); 
</script>

这避免了您在控制服务器设置时可能遇到的任何麻烦,并且无论使用何种服务器技术都可以正常工作。

注意:你必须用相同的方法编写整个对象组,因为在对象标签内放置一个脚本标签意味着“只有在浏览器不支持该对象时才这样做。

【讨论】:

【参考方案7】:

遇到 .XAP 缓存并不少见,这意味着每次部署新版本的 Silverlight 应用程序时,浏览器都不会下载更新的 .XAP 文件。

一种解决方案可能是更改 IIS 属性。您可以按照以下步骤为您的 .XAP 文件打开“启用内容过期 HTTP 标头”选项:

    打开 IIS 管理器 转到“默认网站”并为您的 Silverlight 项目找到网站。 在 ClientBin 下找到 .XAP 文件。 转到 .XAP 文件的属性页面,在 HTTP Headers 选项卡上,打开“Enable Content Expiration”,单击“Expire Immediately”单选按钮。 保存更改。

这样,当您刷新页面时,无需关闭浏览器即可下载最新的 .XAP(仅当存在最新的 .XAP 文件时)。

希望这会有所帮助!

【讨论】:

以上是关于以编程方式使 Silverlight XAP 文件从浏览器缓存中过期的主要内容,如果未能解决你的问题,请参考以下文章

更新后强制浏览器重新加载 Silverlight xap

Silverlight 4.0 - 通过自定义安装程序部署 XAP 并将其配置为 OOB + 提升权限

如何以编程方式在 Silverlight 中创建一个没有框(只是复选)的复选框?

Silverlight 动态本地化

SharePoint 2010/Silverlight:以编程方式传递自定义参数

以编程方式卸载浏览器外的 silverlight 应用程序