【问题标题】:MVC bundle client cachingMVC 捆绑客户端缓存
【发布时间】:2013-01-17 08:13:02
【问题描述】:

默认情况下,MVC 包在客户端缓存 1 年。是否可以手动设置其客户端标头(针对 1 个特定捆绑包)?

我需要为我的其中一个捆绑包设置自定义过期标头。我不能依赖“v=hash”查询字符串,因为这个包是针对外部网站的,每次我更改它时,他们都不会更改指向我的包的 url。

我尝试的是创建一个自定义 Bundle 类(继承 Bundle)并覆盖 GenerateBundleResponse() 方法。这样我可以控制服务器缓存,但自定义客户端缓存的唯一方法是设置 BundleResponse.Cacheability(公共、私有、nocache 等)。但我不能手动设置标题。我可以访问 BundleContext(它是 HttpContext),但是当我在该上下文上设置标头时,它也会对所有其他请求产生影响。

【问题讨论】:

标签: asp.net-mvc asp.net-mvc-4 resourcebundle


【解决方案1】:

不幸的是,没有办法。您可以在捆绑的内部实现中找到原因。在BundleHandler 类中ProcessRequest 调用ProcessRequestBundle 类的内部方法,它在HttpContext.Response.Write 之前调用SetHeaders。因此,客户端缓存在响应写入之前设置为一年。

注意:BundleHandler 是一个内部密封类:internal sealed class BundleHandler : IHttpHandler

BundleHandler 类中:

public void ProcessRequest(HttpContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException("context");
    }
    context.Response.Clear();
    BundleContext context2 = new BundleContext(new HttpContextWrapper(context), BundleTable.Bundles, this.BundleVirtualPath);
    if (!Bundle.GetInstrumentationMode(context2.HttpContext) && !string.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"]))
    {
        context.Response.StatusCode = 304;
    }
    else
    {
        this.RequestBundle.ProcessRequest(context2);
    }
}

Bundle 类中:

internal void ProcessRequest(BundleContext context)
{
    context.EnableInstrumentation = GetInstrumentationMode(context.HttpContext);
    BundleResponse bundleResponse = this.GetBundleResponse(context);
    SetHeaders(bundleResponse, context);
    context.HttpContext.Response.Write(bundleResponse.Content);
}

private static void SetHeaders(BundleResponse bundle, BundleContext context)
{
    if (bundle.ContentType != null)
    {
        context.HttpContext.Response.ContentType = bundle.ContentType;
    }
    if (!context.EnableInstrumentation)
    {
        HttpCachePolicyBase cache = context.HttpContext.Response.Cache;
        cache.SetCacheability(bundle.Cacheability);
        cache.SetOmitVaryStar(true);
        cache.SetExpires(DateTime.Now.AddYears(1));
        cache.SetValidUntilExpires(true);
        cache.SetLastModified(DateTime.Now);
        cache.VaryByHeaders["User-Agent"] = true;
    }
}

【讨论】:

  • 查看 stackoverflow.com/a/34508048/1545567 以解决该问题并完全控制缓存持续时间
【解决方案2】:

ASP.NET MVC 捆绑功能的默认行为是,如果组成捆绑包的任何文件发生更改 - 该捆绑包的查询字符串将自动更改 - 假设您在视图代码中使用以下内容:

@Scripts.Render("bundle name")

所以这意味着如果你有一个新版本的文件在一个包中,下次你的页面渲染一个使用该包的视图时,它会发送一个脚本标签,客户端浏览器在它的缓存中找不到(因为查询字符串不同)。

所以这似乎可以解决您的问题 - 取决于您的意思:

每次我更改时,他们都不会更改指向我的捆绑包的 url 它

【讨论】:

  • 感谢您的回答,但正如我试图解释的那样,我不能依赖“v=hash”查询字符串,因为此捆绑包用于外部网站。
  • 我想我明白 --- 你应该编辑你的问题更清楚一些 - 你希望外部网站的页面包含
  • @stian.net: 只需在包的查询字符串中添加刻度,无论版本是什么。这将使客户端缓存无效。
【解决方案3】:

似乎对我有用的是在捆绑配置中为捆绑提供一个版本号,然后在您的标记中引用新版本。

【讨论】:

  • @cdomination 为什么呢?如果这是一个可行的解决方案,那么发布它有什么问题?
  • @cdomination 只有聪明的用户可以在 cmets 部分发帖,因为至少需要 50 分,否则你只能回答一个问题
【解决方案4】:

虽然没有更好的方法来设置捆绑包的可缓存性,但您可以创建一个 HttpModule 来识别对捆绑包的请求并设置内容可缓存性。

在 Global.asax 上执行此操作具有相同的效果:

    public override void Init()
    {
        this.EndRequest += MvcApplication_EndRequest;
        base.Init();
    }

    void MvcApplication_EndRequest(object sender, EventArgs e)
    {
        var request = this.Request;
        var response = this.Response;

        if (request.RawUrl.Contains("Content/"))
        {
            response.Cache.SetCacheability(HttpCacheability.NoCache);
        }
    }

【讨论】:

    【解决方案5】:

    将额外的查询字符串参数传递给 url,并在每次您希望缓存刷新时更改它。

    例如:https://www.google.co.in/?gfe_rd=cr&ei=EwJeVbHWLcX08wfgwoCoBA&gws_rd=ssl&custom=abc

    最后一个参数是自定义的。

    【讨论】:

      【解决方案6】:

      这是对 Adilson 答案的修改,但无需创建 HttpModule:

      在 MVC 项目的 global.asax.cs 中:

      protected void Application_EndRequest(object sender, EventArgs e) {
          if (Request.RawUrl.Contains("/bundles/")) {
              // My bundles all have a /bundles/ prefix in the URL
              Response.Cache.SetExpires(DateTime.Now.AddHours(2));
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-18
        • 2012-07-26
        • 2019-04-24
        • 1970-01-01
        相关资源
        最近更新 更多