禁用整个ASP.NET网站的浏览器缓存


199

我正在寻找一种方法来禁用整个ASP.NET MVC网站的浏览器缓存

我发现以下方法:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.Cache.SetNoStore();

还有一个meta标签方法(因为某些MVC操作通过Ajax发送部分HTML / JSON,而没有head meta标签,所以它对我不起作用)。

<meta http-equiv="PRAGMA" content="NO-CACHE">

但是我正在寻找一种简单的方法来禁用整个网站的浏览器缓存。


Answers:


92
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();

所有请求都首先通过default.aspx进行路由-因此,假设您可以在其后弹出代码。


17
我将其放入Application_BeginRequest()中的Global.asax.cs中。我不相信这是default.aspx的问题...另一个问题:它优先于[OutputCache]属性吗?
chris166

5
我喜欢简单地创建Global Action Filter并以这种方式放置这些内容的想法。无需担心Default.aspx和Global.asax。
基思·阿德勒

13
将其放在Application_BeingRequest中可能会导致一些问题。如果您的图片通过.net运行时进行路由(如果您使用通配符映射获取漂亮的url,则可能会发生这种情况),那么浏览器中将不会缓存任何图片。由于每个页面请求都将重新下载所有图像,因此这确实会减慢页面加载时间。
herbrandson

4
以编程方式使用任何内容将始终覆盖任何声明的Attribute。换句话说,使用OP的代码将覆盖任何声明的[OutputCache]属性。
戴夫·布莱克

关于如何进行抽烟测试并验证缓存禁用是否真正起作用的任何想法?
paaone

366

创建一个从IActionFilter继承的类。

public class NoCacheAttribute : ActionFilterAttribute
{  
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();

        base.OnResultExecuting(filterContext);
    }
}

然后将属性放在需要的地方...

[NoCache]
[HandleError]
public class AccountController : Controller
{
    [NoCache]
    [Authorize]
    public ActionResult ChangePassword()
    {
        return View();
    }
}

19
您可能应该使用filterContext.HttpContext.Response而不是HttpContext.Current.Response,因为HttpContext.Current返回MVC之前的HttpContext对象,而filterContext.HttpContext返回MVC之后的HttpContextBase。它提高了可测试性和一致性。
mkedobbs 2010年

5
IActionFilter已经在ActionFilterAttribute上实现,因此您无需重复它。
Andrew Davey 2010年

104
在当前版本的ASP.NET MVC中,您可以简单地使用OutputCacheAttribute来防止缓存:[OutputCache(NoStore = true,Duration = 0,VaryByParam =“ None”)]
Ashley Tate,2010年

9
我想指出,我花了几天时间在阳光下为ASP.NET MVC使用每个“在您的代码中输入此信息以停止缓存”解决方案,包括对此问题的公认答案,但没有用。这个答案-属性-起作用了。+ 1M Rep,如果我可以...
Tom Kidd

5
您可能需要if (filterContext.IsChildAction) return;在顶部添加-如果外部动作调用以NoCache属性装饰的子动作,则可以防止外部动作“不缓存” 。换句话说,NoCache如果其他动作执行子动作,则该属性不会泄漏给其他动作。同样,类名称应NoCacheAttribute符合公认的属性命名约定。
雅各布·科内基

132

不用自己动手,只需使用为您提供的功能。

如前所述,请勿禁用所有内容的缓存。例如,应该缓存在ASP.NET MVC中大量使用的jQuery脚本。实际上,理想情况下,无论如何,您都应该使用CDN,但是我的意思是应该缓存某些内容。

我发现在这里效果最好,而不是到处都撒满[OutputCache]是使用一个类:

[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class NoCacheController  : Controller
{
}

您要禁用缓存的所有控制器,然后从该控制器继承。

如果您需要覆盖NoCacheController类中的默认值,只需在action方法上指定缓存设置,然后Action方法上的设置将优先。

[HttpGet]
[OutputCache(NoStore = true, Duration = 60, VaryByParam = "*")]
public ViewResult Index()
{
  ...
}

4
@Ozziepeeps,您的评论不正确。msdn文档讨论了浏览器缓存以及一个简单的测试,它将显示此属性将缓存控制响应标头从“缓存控制:私有”更改为“缓存控制:公共,无存储,最大年龄= 0”,而没有使用属性。
Adam Tuliper-MSFT 2011年

2
也可以-您可以使用此属性控制所有三个位置(服务器,代理,客户端),因此绝对可以控制超出服务器缓存的范围。有关其他更多信息,请参见asp.net/mvc/tutorials/…
Adam Tuliper-MSFT 2011年

1
+1“如果您需要覆盖NoCacheController类中的默认值,只需在操作方法上指定缓存设置,然后在操作方法上设置优先。”
Korayem

2
请注意,如果您[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]在课程级别使用,则您的课程中不能有PartialViews。
维维安河

1
当存在两个条件时,OutputCache方法不会阻止IE缓存:1)该操作没有参数,并且2)该操作仅通过Content(someText)返回了文本。当我返回JSON并接受一个参数时,IE缓存将被正确击败。
Kasey Speakman 2013年

10

您可能要为控制器呈现的所有页面(即HTML页面)禁用浏览器缓存,但是要对脚本,样式表和图像等资源保持缓存到位。如果您使用的是MVC4 +捆绑和最小化,则需要保留脚本和样式表的默认缓存持续时间(非常长的持续时间,因为缓存是根据对唯一URL的更改而不是基于时间而无效的)。

在MVC4 +中,要禁用所有控制器之间的浏览器缓存,但要保留控制器不提供的任何内容,请将其添加到FilterConfig.RegisterGlobalFilters

filters.Add(new DisableCache());

定义DisableCache如下:

class DisableCache : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}

不幸的是,这似乎不起作用,因为退出后点击返回按钮会显示该页面。
2015年

6

我知道此答案与问题并非100%相关,但可能会对某人有所帮助。

如果要禁用整个ASP.NET MVC网站的浏览器缓存,而只想临时执行此操作,则最好禁用浏览器中的缓存。

这是Chrome中的屏幕截图


这正是我一直在寻找的...在开发过程中,如果我更改了.js文件,当我很难进行很少的故障排除/刷新/测试周期时,要立即通过它是一个很大的痛苦。这太完美了,谢谢!刚使我的客户端调试生活变得更加轻松
jleach '16

2

我实现了所有先前的答案,但仍然有一种观点无法正常工作。

原来,我遇到问题的视图的名称为“ Recent”。显然,这混淆了Internet Explorer浏览器。

在将视图名称(在控制器中)更改为其他名称(我选择为“ Recent5”)之后,上述解决方案开始起作用。


0

您可以在Global.asax文件中尝试以下代码。

protected void Application_BeginRequest()
    {
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetExpires(DateTime.UtcNow.AddHours(-1));
        Response.Cache.SetNoStore();
    }

-1

用户界面

<%@ OutPutCache Location="None"%>
<%
    Response.Buffer = true;
    Response.Expires = -1;
    Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-1);
    Response.CacheControl = "no-cache";
%>

背景

Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
Response.Expires = -1;          
Response.Cache.SetNoStore();

1
即使在技术上正确,也需要解释性的散文
rmalayter
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.