MVC4请求标头

时间:2014-08-14 15:47:06

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

我在MVC网络应用程序中有相当奇怪的行为。

[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不起作用?

3 个答案:

答案 0 :(得分:1)

" Cache-Control" ASP.NET中的响应标头是特殊的,不应该显式设置。相反,请使用已经找到Response.Cache对象的第一类API。

答案 1 :(得分:0)

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

基本上,您可以创建另一个名为[ApplyCache]的过滤器,以应用于您不想设置no-cache的操作方法,而在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());
}

答案 2 :(得分:0)

行。这就是我发现的。如果您在代码中使用(任何其他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();