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

24

如何避免Web浏览器缓存Silverlight XAP文件?

我希望在开发过程中避免手动清除浏览器缓存,因此寻找一种服务器端的程序化方法。

7个回答

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

这是一个非常好的回答,比很多其他回答都要好(我在这里看到你很多次给出这个答案)。虽然我是Web开发的新手,但在阅读下面的教程之后...我可以看到这正是XAP缓存所需要的。这真的是一个很好的解决方案。缓存教程 - Mike S.
这不会强制浏览器永远不缓存XAP吗?还是只有在XAP完全相同时才会缓存它? - Didier A.
有没有办法通过Web.Config来实现这个?我的项目托管在一个我无法访问IIS管理的服务器上。 - Marlon

8
在HTML页面的< object >元素中,为XAP添加查询参数:
  • clientBin/MyApp.xap?rev=1
  • clientBin/MyApp.xap?rev=2
请注意,如果忽略这些参数会破坏缓存。在IE8中,有一些缓存管理工具:
  • 尝试缓存...始终从服务器刷新
  • 尝试缓存...清除此域的浏览器缓存...
请使用这些工具来管理缓存。

当引用静态资源的URL是动态生成的时,修订号可以非常有效。但是,要使其动态发生并且没有自定义基础设施需要相当大的工作量,否则开发人员必须手动记住升级版本号。如果该资源在多个位置使用,则情况会更糟。由于不太可能从单个客户端频繁请求XAP,因此偶尔的“未修改”响应更为理想。 - AnthonyWJones

6

这里提出的解决方案{{link1:类似于}Michael的,但是它是自动的,并且保证客户端始终获取新版本。根据您的情况,这可能效率低下。

由于Lars在他的评论中说他不在Stack Overflow上,我在这里复制回复。

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

  ....

</object>

我尝试了这个方法,虽然我可以调试并看到“param”正确构建,但Response.Write在我的示例中写入<object>标记的开头。有什么解决办法吗? - dougajmcdonald
哦...这真的很奇怪。也许你可以Response.Write整个对象标记,包括参数? - Jedidja
确实很奇怪,我想把整个东西写出来,我也做到了。似乎我们正在使用的框架不能处理aspx/Response流中response.writes所在的位置。我会与他们联系并看看他们是否能指引我正确的方向。感谢您的回复。 - dougajmcdonald
无法用于 PRISM 应用程序,其中模块 XAP 是由 shell XAP 下载的。 - Sam

5

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

像这样...

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文件的路径中添加了一个查询参数,以便通过版本控制来管理它。

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()
    }
}

2

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

然而,至少对于调试情况来说,很容易在JavaScript中编写<object>和<param>标签,以便每次使用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>

这样可以避免您可能在控制服务器设置方面遇到的任何麻烦,并且无论使用哪种服务器技术,都能正常工作。
注意:您必须使用相同的方法编写整个对象组,因为将脚本标签放在对象标签内意味着“仅在浏览器不支持对象时执行此操作”。

2
很常见的情况是遇到.XAP缓存,这意味着每次部署新版本的Silverlight应用程序时,浏览器不会下载更新的.XAP文件。
解决方法之一是更改IIS属性。您可以按照以下步骤为.XAP文件打开“启用内容过期HTTP标头”选项:
1. 打开IIS管理器 2. 转到“默认网站”,找到Silverlight项目的网站。 3. 在ClientBin下找到.XAP文件。 4. 转到.XAP文件的属性页面,在HTTP标头选项卡上打开“启用内容过期”,单击“立即过期”单选按钮。 5. 保存更改。
这样,只要有最新的.XAP文件,刷新页面时就会下载最新的.XAP文件,而无需关闭浏览器。
希望这能帮到你!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接