【问题标题】:Caching not working right in my ASP.NET MVC website?缓存在我的 ASP.NET MVC 网站中无法正常工作?
【发布时间】:2010-11-29 01:27:16
【问题描述】:

我正在尝试在我的 ASP.NET MVC 网站中使用 OutputCaching。问题是,当我尝试更改我的查询字符串参数的值时,它会返回请求的第一个项目的数据!

这是我的代码(更改了参数名称)...

[ApiAuthorize]
[HandleErrorAsJson]
public class SearchController : Controller
{
    [AcceptVerbs(HttpVerbs.Get)]
    [OutputCache(Duration = 60, VaryByParam = "*")]
    public ActionResult ScoreCard(string foo, byte? bar, byte? pewpew)
    {
    ..
    }
}
  • 注意 1:ApiAuthorize - 自定义属性,用于检查名为“Key”的查询字符串参数并检查内存字典,以查看它是否存在。
  • 注意 2:HandleErrorAsJson - 自定义属性,如果抛出/抛出异常,则以 json 格式返回错误消息。

这是我对这个操作进行的两个示例调用:-

因此,第一次调用 (foo = hello world, Pew Pew) 的数据返回 200 OK。 然后第二个 api 调用返回 200 OK,但包含上一次调用的数据。

另外,我没有使用任何代理服务器。 如果我注释掉 OutputCache 属性,一切都很好。

我也尝试了以下(每次我需要缓存时手动列出).....

[OutputCache(Duration = 60, VaryByParam = "foo,key,bar,pewpew")]

运气不好:(

注意我需要确保将 API 'Key' 参数作为缓存唯一键的一部分。我不希望人们搜索相同的东西,但如果第二个人没有正确的键,他们不应该得到缓存的结果,而是一条错误消息(从技术上讲,它是 401 Not Authorized,但是反正)...

想法?

【问题讨论】:

    标签: asp.net-mvc caching outputcache varybyparam


    【解决方案1】:

    VaryByParam 中的参数列表应该以分号分隔,而不是逗号分隔。试试看。也就是说,* 应该可以工作。

    【讨论】:

    • +1 更直接地关注手头的问题。虽然我不认为这是他在这里遇到的唯一问题。在下面也回复了您的评论。
    【解决方案2】:

    我使用过滤器进行输出缓存,它可以为调试提供编程控制,并在需要时进行设置。随意使用它,看看在这里设置它是否会产生我认为可能的不同(还要确保清除任何以前的缓存)

    public class CacheFilterAttribute : ActionFilterAttribute
        {
            private const int Second = 1;
            private const int Minute = 60 * Second;
            private const int Hour = 60 * Minute;
            public const int SecondsInDay = Hour * 24;
    
    
            /// <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 int DurationInDays
            {
                get { return Duration / SecondsInDay; }
                set { Duration = value * SecondsInDay; }
            }
    
            public CacheFilterAttribute()
            {
                Duration = 10;
            }
    
            public override void OnActionExecuted(ActionExecutedContext filterContext)
            {
                if (Duration <= 0) return;
    
                HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
                TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
    
                cache.SetCacheability(HttpCacheability.Public);
                cache.SetExpires(DateTime.Now.Add(cacheDuration));
                cache.SetMaxAge(cacheDuration);
                cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
            }
        }
    

    到目前为止,我只是将它用于网站的一个非常静态的部分,所以可以这样调用

    [CacheFilter(DurationInDays = 1)]
    

    显然,您只是想扩展它以将 VaryByParams 作为属性公开,可以提供但听起来您知道该怎么做。

    【讨论】:

    • 出于兴趣,你为什么要在这里创建自己的属性?
    • 我申请了几个视图,并且会做更多。我不是 100% 使用您在上面看到的确切设置,因此我可以轻松调整并知道它已应用于任何地方。在设置缓存时,我仍然没有确定是否添加更多标头。当然,如果我发现这是一个坏主意,我可以将其作为 OutputCache 属性的干净扩展,并且不会丢失任何内容。因此,简而言之,如果出现任何风险,通向安全的明确途径可以有所收获。
    • 他在这里所做的并没有错,但它并没有回答你的问题。他创建的过滤器会影响 浏览器 缓存,而不是服务器缓存。这样做是合法的,我不知道 ASP.NET MVC 中内置的任何东西可以做到这一点。它也隐含地提出了一个很好的观点,那就是这里有两个不同的缓存,一个在浏览器中,一个在服务器中。在我看来,您的问题与服务器缓存有关,但最好用 Firebug 或 Fiddler 仔细检查。
    • @Craig 感谢您指出这一点,我假设 HttpCacheability.Public 包含服务器,但您是对的,它没有。而且看起来不可能有完整的选择。那就是你可以设置 HttpCacheability.ServerAndPrivate 但这会排除我肯定想要的代理(ISP)。但是,由于 AppendCacheExtension("must-revalidate, proxy-revalidate");当我添加它时,我在调试时确认了这一点,因此它是一个服务器缓存,尽管没有完美表达并且可能存在问题。
    • AppendCacheExtension 做了一件事:将文本添加到 HTTP 响应的标头。请参阅msdn.microsoft.com/en-us/library/… 它向响应添加文本,而不是请求,告诉您它正在影响什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多