【问题标题】:MVC4 Request headersMVC4 请求标头
【发布时间】:2014-08-14 15:47:06
【问题描述】:

我的 MVC Web 应用程序有一些奇怪的行为。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class NoCacheFilterAttribute : ActionFilterAttribute
{
            ctx.Response.AddHeader("Cache-Control", "no-cache);
}

我将这个过滤器类添加到 GlobalFilterCollection 以便它在每个操作上运行。

我正在尝试在我的一种家庭控制器操作方法中选择性地覆盖此标头。 Response.Headers.Remove("缓存控制"); Response.AddHeader("Cache-Control", "private,must-revalidate,proxy-revalidate");

问题不是这些代码设置了正确的值。当我检查响应标头中的值时,Cache-Control 设置为“private,s-maxage=0”。我扫描了我所有的代码,看看我是否在任何地方都明确地这样做了,但我没有看到自己这样做。奇怪的是如果我打电话 Response.Cache.SetNoStore();或 Response.Cache 的任何方法。 Cache-Control 的响应值随之改变。我不确定为什么 Response.AddHeader 或 AppendHeader 不起作用?

【问题讨论】:

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


    【解决方案1】:

    ASP.NET 中的“Cache-Control”响应标头很特殊,不应显式设置。相反,请使用您已经找到的挂在 Response.Cache 对象上的一流 API。

    【讨论】:

      【解决方案2】:

      你能在执行ctx.Response.AddHeader("Cache-Control", "no-cache)之前添加一些条件逻辑来解决它吗?

      基本上,您可以创建另一个名为 [ApplyCache] 的过滤器来应用于您不希望设置无缓存的操作方法,并且在 NoCacheFilterAttribute 中,您可以这样做,

      [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
      public class NoCacheFilterAttribute : ActionFilterAttribute
      {
         public override void OnActionExecuted(HttpActionExecutedContext ctx)
         {
            if (!ctx.ControllerContext.ControllerDescriptor.GetFilters().Contains(new ApplyCache()) && !ctx.ActionDescriptor.GetFilters().Contains(new ApplyCache())              
               {
                  ctx.Response.Headers.Add("Cache-Control", "no-cache");
               }
         }
      }
      

      对于 MVC,这可能是,

      public class ApplyCache: System.Web.Mvc.ActionFilterAttribute
          {
          }
      
      public class NoCache: System.Web.Mvc.ActionFilterAttribute
          {
      
              public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
              {
                 if (!actionExecutedContext.ActionDescriptor.IsDefined(typeof(ApplyCache), true))
                 {
                      actionExecutedContext.RequestContext.HttpContext.Response.AddHeader("Cache-Control", "no-cache");
                 }
              }
          }
      

      并且您想将这两个过滤器都添加到您的全局集合中。

      public static void RegisterMvcFilters(GlobalFilterCollection filters)
      {
          filters.Add(new ApplyCache());
          filters.Add(new NoCache());
      }
      

      【讨论】:

      • 好吧。当我尝试添加到 GlobalFilterCollection 时,这不起作用。看起来您建议的 ActionFilterAttribute 属于 System.Web.Http.Filters 而不是 System.Web.Mvc
      • 我以为是 Web API。对于 MVC,您可以遵循类似的方法,但将条件检查更改为 !actionContext.ActionDescriptor.IsDefined(typeof(ApplyCache), true)
      • 代码执行良好。尽管如此,在 chrome 和 FF 检查元素窗口中检查时,标题值不会改变(是的,我也确实清除了浏览器端的缓存)。我添加了断点来检查标头值是否发生变化,我确实看到 Response.Headers 集合中的值发生变化。但是当页面返回时,Cache-Control 中的值不会改变。出于某种原因,它更喜欢在写入最终内容时使用来自 Response.Cache 的值
      【解决方案3】:

      好的。这是我发现的。如果您使用以下代码(任何其他 NuGet 库可能正在设置标头),您可以随时在代码中的任何位置使用以下代码:

       Response.Cache.SetNoStore(); //or any other .SetXXX; methods
      

      ,标头被写入缓冲区,如果您发出以下代码(在 ActionFilterAttribute 中使用此代码的一些示例):

       HttpContext ctx = HttpContext.Current; 
       ctx.Response.AppendHeader("Cache-Control", "private, must-revalidate, proxy-revalidate ");
       ctx.Response.AddHeader("Cache-Control", "private, must-revalidate, proxy-revalidate ");
       ctx.Response.Headers.Set("Cache-Control", "no-cache, no-store, must-revalidate, proxy-revalidate");
      

      修改表头,表头值不写。重置标头的唯一方法是发出以下代码行,然后发出上面的代码或调用 Response.Cache.SetXXX 方法。

       ctx.Response.ClearHeaders();
      

      Response.Cache 不提供重置使用 .SetXXXX 方法设置的响应标头值的机制。如果从未调用过 Response.Cache.SetXXX 方法,则调用 Response.AppendHeader、AddHeader 或 Headers.Set 将起作用,而无需调用 Response.ClearHeaders();

      【讨论】:

        猜你喜欢
        • 2017-10-07
        • 2015-07-13
        • 1970-01-01
        • 2016-05-06
        • 2019-01-08
        • 2019-01-04
        • 2013-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多