在MVC 3中禁用部分视图的缓存

21

我在一个部分视图上遇到了一个问题,它被缓存了,而实际上它不应该被缓存。这个部分视图用于显示页面上的登录/注销状态。它使用以下简单代码来确定要显示哪个链接

@if(Request.IsAuthenticated) {    
    <a href="@Url.Action("LogOff", "Account", new { area = "" })">Log Off</a> 
}
else {
    <a href="@Url.Action("LogOn", "Account", new { area = "" })">Log On</a>
}

这个部分视图被用于我 MVC3 应用的所有页面中,使用的是

@Html.Partial("_HeaderView")  

在我的大多数控制器中,我都定义了输出缓存,这样我就可以利用缓存我的内容。

[OutputCache(Duration = 86400, VaryByParam = "*")]

现在我的问题是整个页面被缓存了,而我不希望局部视图被缓存。这导致了错误的行为,有时候即使用户没有登录,它也会显示LogOff等。是否有一种方法可以缓存所有内容,除了相关的局部视图?


Nick,抱歉不得不在这里添加评论。无论如何,当我删除Nostore并将持续时间更改为1时,它可以正常工作。现在唯一的问题是,当用户登录时,他们会被带到主页,但我必须明确地刷新它才能使更改生效(显示注销而不是登录)。 - SimpleUser
6个回答

18

您可以通过在显示 _HeaderView 部分的控制器上添加以下装饰器来禁用缓存:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult HeaderView()
{
    return PartialView("_HeaderView");
}

嗨,Nick。感谢你的建议。但是我现在没有与部分视图相关联的控制器操作(至少目前没有)。我正在使用Html.Partial()进行调用。唯一的解决方法是拥有上述控制器操作吗? - SimpleUser
谢谢Nick。我会实施这些更改并告诉您结果的。 - SimpleUser
你好Nick。当我加入outputcache注释时,部分视图根本不显示。这是我的两个控制器操作的样子[OutputCache(Duration=86400, VaryByParam="*")] public ActionResult Index() { return View(); }[OutputCache(Duration = 0, VaryByParam = "*")] [ChildActionOnly] public ActionResult HeaderView() { return PartialView("_HeaderView"); }从Index页面中,我正在调用Html.Action来显示部分视图。 - SimpleUser
初步测试表明,您只需要指定“NoStore”和“Duration”参数。实际上,我一开始只指定了“NoStore = true”,但是出现了一个错误,说需要“Duration”。在将“Duration = 0”放置后,一切似乎都按预期工作了。您能确认一下吗?我喜欢尽可能少的代码,尤其是当我们处理硬编码字符串时。 - julealgon
3
刚刚进行了更多的测试,似乎我可以使用 Location = OutputCacheLocation.None 而不是 Duration = 0,这样更加清晰明了 :) - julealgon
显示剩余8条评论

9

我确实尝试了这个,但是它并没有像我预期的那样起作用。我仍然遇到了与在部分操作上使用outputcache属性相同的问题,即需要手动刷新主页。 - SimpleUser
我很乐意帮忙,但是没有看到你的代码会让这件事变得困难 :) 不过它对我起作用了。在测试时,请记住正确的浏览器设置(有时它们会覆盖服务器设置,并导致错误地认为某些东西不起作用) - Paweł Staniec
不,那只是我思维迟缓。显然在感冒的情况下工作并不明智。但现在这个问题已经解决了。谢谢你的帮助。 - SimpleUser

3
我们应该在Web.config文件中设置缓存配置文件,而不是在页面上单独设置缓存值,以避免冗余代码。我们可以使用OutputCache属性的CacheProfile属性引用配置文件。除非页面/方法覆盖这些设置,否则此缓存配置文件将应用于所有页面。
<system.web>
  <caching>
    <outputCacheSettings>
      <outputCacheProfiles>
        <add name="CacheProfile" duration="60" varyByParam="*" />
      </outputCacheProfiles>
    </outputCacheSettings>
  </caching>
</system.web>

如果您想禁用返回部分视图[_HeaderView]的操作的缓存,您可以通过如下所示装饰该特定操作方法来覆盖配置缓存设置:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult RenderPartialView()
{
    return PartialView("_HeaderView");
}

希望这能对你有所帮助!

1
在重新进入MVC后,花了一点时间才弄清楚这个问题。只需直接将缓存设置放在Partial Header View中。例如在显示用户名时。不需要全局或服务器端代码。唯一的问题是一旦页面被缓存,登录后不会立即刷新。但是我们在浏览产品时保持速度。在我们的情况下,这是一个可以接受的权衡。
    @if ( Request.IsAuthenticated)
    {
            @* 当我们已经认证时,不再缓存! *@
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    HttpContext.Current.Response.Cache.SetNoStore();
    HttpContext.Current.Response.Cache.SetNoServerCaching();
            @*@Html.Raw(DateTime.Now.ToString())*@
    @Html.ActionLink("欢迎 " + ( String.IsNullOrEmpty(((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirstValue("UserName")) ? User.Identity.Name : ((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirstValue("UserName")), "Index", "Manage", routeValues: new { Area = "Store" }, htmlAttributes: new { title = "管理"})
    }
    else
    {
    }


1
这对我有效...
 public ActionResult LogOff()
 {
     AuthenticationManager.SignOut();  
     var url = Url.Action("Index", "Web"); 
     HttpResponse.RemoveOutputCacheItem(url);           
     return RedirectToAction("Index", "Web");
 }

+1 我尝试了所有其他的解决方案,它们都不太好用,但这个对我来说非常好用...谢谢 :) 注意:我没有使用AuthenticationManager.Signout()。 - Prince Ashitaka

1

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