浏览器缓存是否可以通过代码清除?

时间:2010-09-18 13:27:25

标签: c# asp.net browser caching

我的网站上有一个菜单,根据用户是否登录而改变。使用浏览器缓存时,菜单会“卡在”任一状态,并且会让用户感到困惑。

他们将登录,但菜单不会更新,因为它仍然在未经身份验证的状态下缓存...反之亦然。

这通常如何处理?我们可以从代码中刷新用户的浏览器缓存吗?或者我不允许浏览器缓存? (宁愿使用它,速度非常好)。

更新

以下是我在asp.net mvc 2应用程序中设置客户端浏览器缓存的方法:

public class CacheFilterAttribute : ActionFilterAttribute {
    /// <summary>
    /// Gets or sets the cache duration in seconds. The default is 10 seconds.
    /// </summary>
    /// <value>The cache duration in seconds.</value>
    public int Duration { get; set; }

    public CacheFilterAttribute() { Duration = 10; }

    public override void OnActionExecuted(ActionExecutedContext filterContext) {
        if (Duration <= 0) return;

        var cache = filterContext.HttpContext.Response.Cache;
        var cacheDuration = TimeSpan.FromSeconds(Duration);

        cache.SetCacheability(HttpCacheability.Public);
        cache.SetExpires(DateTime.Now.Add(cacheDuration));
        cache.SetMaxAge(cacheDuration);
        cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
    }
}

然后将[CachFilter(持续时间= 60)]应用于我的操作。 (注意,我从Kazi Manzur Rashid's Blog

获得了上面的代码

2 个答案:

答案 0 :(得分:2)

我一直在玩一个动作过滤器来使用条件请求和电子标签来模拟这种行为,这是纯粹的客户端缓存,因此这里不涉及输出缓存。您仍然会收到服务器的请求,但不会调用该操作,如果客户端仍处于新鲜状态,客户端将使用本地缓存。

/// <summary>
/// Handles client side caching by automatically refreshing content when switching logged in identity
/// </summary>
public class ClientCacheByIdentityAttribute : ActionFilterAttribute
{
    /// <summary>
    /// Sets the cache duraction in minutes
    /// </summary>
    public int Duration { get; set; }

    /// <summary>
    /// Check for incoming conditional requests
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.IsChildAction || filterContext.HttpContext.Request.RequestType!="GET" || filterContext.Result!=null)
        {
            return;
        }

        string modifiedSinceString = filterContext.HttpContext.Request.Headers["If-Modified-Since"];
        string noneMatchString = filterContext.HttpContext.Request.Headers["If-None-Match"];

        if (String.IsNullOrEmpty(modifiedSinceString) || String.IsNullOrEmpty(noneMatchString))
        {
            return;
        }

        DateTime modifiedSince;

        if (!DateTime.TryParse(modifiedSinceString, out modifiedSince))
        {
            return;
        }

        if (modifiedSince.AddMinutes(Duration) < DateTime.Now)
        {
            return;
        }

        string etag = CreateETag(filterContext.HttpContext);

        if (etag == noneMatchString)
        {
            filterContext.HttpContext.Response.StatusCode = 304;
            filterContext.Result = new EmptyResult();
        }
    }

    /// <summary>
    /// Handles setting the caching attributes required for conditional gets
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.HttpContext.Request.RequestType == "GET" && filterContext.HttpContext.Response.StatusCode == 200 && !filterContext.IsChildAction && !filterContext.HttpContext.Response.IsRequestBeingRedirected)
        {
            filterContext.HttpContext.Response.AddHeader("Last-Modified", DateTime.Now.ToString("r"));
            filterContext.HttpContext.Response.AddHeader("ETag", CreateETag(filterContext.HttpContext));
        }
    }

    /// <summary>
    /// Construct the ETag
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private static string CreateETag(HttpContextBase context)
    {
        return "\"" + CalculateMD5Hash(context.Request.Url.PathAndQuery + "$" + context.User.Identity.Name) + "\"";
    }

    /// <summary>
    /// Helper to make an MD5 hash
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    private static string CalculateMD5Hash(string input)
    {
        MD5 md5 = MD5.Create();
        byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
        byte[] hash = md5.ComputeHash(inputBytes);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
    }
}

答案 1 :(得分:1)

你可能想尝试甜甜圈洞缓存并缓存菜单以外的所有内容。 Scott Guthrie在这个主题上有一个很好的article