1

我在 asp.mvc 中注销时遇到问题。用户可以按返回按钮,他将看到最后访问的页面。

我进行了一些搜索并找到了这样的解决方案:

this.Response.Cache.SetExpires(DateTime.UtcNow.AddYears(-1));
this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
this.Response.Cache.SetNoStore();

但我应该将它添加到每个页面以使其正常工作。

是否有某种方法可以禁用 mvc 应用程序中所有控制器的所有 GET 请求的缓存,然后为其中一些控制器启用它,例如使用属性或自定义过滤器?

4

3 回答 3

3

让它在全球范围内工作并不多。我们过去所做的是创建一个派生自 ActionFilter 的类,然后将其作为全局操作过滤器添加到 global.asax 中。另请注意,实际上强制所有浏览器重新加载并非易事。即使是下面的代码也并不总是适用于 Safari,这通常必须通过 body 标签或类似的空加载来欺骗。

 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Web.Mvc;

 /// <summary>
 /// Action filter that instructs the page to expire.
 /// </summary>
 public class PageExpirationAttribute : ActionFilterAttribute
 {
    /// <summary>
    /// The OnActionExecuted method.
    /// </summary>
    /// <param name="filterContext">The current ActionExecutedContext. </param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
       base.OnActionExecuting(filterContext);

       filterContext.HttpContext.Response.ClearHeaders();
       filterContext.HttpContext.Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate, post-check=0, pre-check=0, max-age=0");
       filterContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
       filterContext.HttpContext.Response.AppendHeader("Keep-Alive", "timeout=3, max=993");
       filterContext.HttpContext.Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
    }
 }

如果您希望能够排除某些页面,可以创建另一个属性,您可以将其应用于控制器或方法。您的 OnActionExecuting() 可以检查该属性是否存在:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class AllowCachingAttribute : Attribute 
{ 
}

添加到 OnActionExecuting 的近似代码

using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Web.Mvc;

 /// <summary>
 /// Action filter that instructs the page to expire.
 /// </summary>
 public class PageExpirationAttribute : ActionFilterAttribute
 {
    /// <summary>
    /// The OnActionExecuted method.
    /// </summary>
    /// <param name="filterContext">The current ActionExecutedContext. </param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
       base.OnActionExecuting(filterContext);

       bool skipCache = filterContext.ActionDescriptor.IsDefined(typeof(AllowCachingAttribute), true)
                || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowCachingAttributee), true);

       if (!skipCache)
       {

       filterContext.HttpContext.Response.ClearHeaders();
       filterContext.HttpContext.Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate, post-check=0, pre-check=0, max-age=0");
       filterContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
       filterContext.HttpContext.Response.AppendHeader("Keep-Alive", "timeout=3, max=993");
       filterContext.HttpContext.Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
       }
    }
 }
于 2012-05-30T16:52:22.877 回答
0

您可以创建一个实用程序类并添加一个执行上述代码的公共静态方法,然后调用它。然后在控制器的方法中,调用实用程序方法。我将提供一些代码:

namespace App
{
    public class Utility
    {
        public static void SetResponsAttributes(HttpResponseBase theResponseObject)
        {
            if (theResponseObject == null) return;

            theResponseObject.Cache.SetExpires(DateTime.UtcNow.AddYears(-1));
            theResponseObject.Cache.SetCacheability(HttpCacheability.NoCache);
            theResponseObject.Cache.SetNoStore(); 
        }
   }
}
于 2012-05-30T16:12:41.210 回答
0

为什么不设置一个会话标志来指示登录指示器并将整个视图内容包装在一个 if 块中。在注销时放弃会话。

于 2012-05-30T16:22:48.757 回答