2012-06-12 31 views
11

我已经添加输出缓存的一对夫妇的行动,我的应用程序进行一些简单的性能提升。但是,这些操作还需要在每次请求(它是一个视图计数器)后通过点击Redis数据库来增加计数器。与输出缓存和其他行动工作滤清器

起初,我想我可能只是调整中的操作筛选器执行,以确保观看次数的计算顺序:

public class CountersAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     //increment my counter all clever like 
     base.OnResultExecuted(filterContext); 
    } 
} 

但没有工作;显然OutputCacheAttribute不像一个正常的操作过滤器。然后我尝试实现一个自定义输出缓存:

public class OutputCacheWithCountersAttribute : OutputCacheAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     //straight to the source to get my headcount! 
     base.OnResultExecuted(filterContext); 
    } 
} 

不,也没有工作;一旦动作被缓存,动作过滤器似乎完全被忽略。游民。

所以,呃,有没有办法(没有实现自定义输出缓存提供者)对我来说,我保证意见正确计算是干净和理性呢?

回答

13

OutputCacheAttribute有限制的方式,有一个名为DonutOutputCache的自定义属性由Paul Hiles开发,有助于克服这些限制。

一个支持的重要特点之一是,你可以有一个动作过滤器,可调用的所有连动作标志着次高速缓存属性或没有。

例如,要缓存的时间为5秒的动作,并在同一时间,你想用一个LogThis过滤器记录每个动作接收到一个请求时,你可以做到这一点只需通过下方,

[LogThis] 
[DonutOutputCache(Duration=5, Order=100)] 
public ActionResult Index() 

Paul

是的,与内置OutputCacheAttribute不同,即使从缓存中检索页面,也会执行动作过滤器 。唯一需要注意的是 需要注意过滤顺序。如果您 行动过滤器实现OnResultExecuting或OnResultExecuted 那么这些方法将在所有的情况下被执行,但对于 OnActionExecuting和OnActionExecuted,他们将仅 过滤器的DonutOutputCacheAttribute之前运行执行。这是由于 MVC阻止后续过滤器执行的方式,因为当您设置filterContext.Result属性时,我们需要为 输出缓存执行此操作。

我不认为你可以依靠在操作筛选 是在一个动作或控制器中定义的顺序。为了确保一个过滤器运行 之前另一个,你可以利用订单属性,是所有ActionFilterAttribute实现本 的。没有 顺序属性设置任何动作,默认为-1的值,这意味着他们将 之前其有明确的订单值滤波器执行。

因此,你的情况,你可以添加顺序= 100到 DonutOutputCache属性和所有其他过滤器 缓存过滤器前将执行。

+0

这很奇妙,除了现在我的VaryByCustom参数不工作。 GetVaryByCustomString()在全局变量中被调用,但是Donut似乎没有遵守我所做的Response.Cache更改(即关闭认证用户的缓存)。 – Dusda

+0

context.Response.Cache.SetCacheability(HttpCacheability.NoCache); context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(-1)); context.Response.Cache.SetNoStore(); context.Response.Cache.SetNoServerCaching(); 这些是我的Response.Cache更改;无论如何,甜甜圈似乎无视它们并缓存它。 – Dusda

+0

我将页面视图移动到ajax调用,而不是再混淆VaryByCustom。但是,给出的答案是解决这个问题的一个很好的方法。谢谢:D。 – Dusda

0

的原因实际上是在.NET源,并没有与DonutOutputCache做:

public void SetCacheability(HttpCacheability cacheability) 
{ 
    if (cacheability < HttpCacheability.NoCache || HttpCacheability.ServerAndPrivate < cacheability) 
    throw new ArgumentOutOfRangeException("cacheability"); 
    if (HttpCachePolicy.s_cacheabilityValues[(int) cacheability] >= HttpCachePolicy.s_cacheabilityValues[(int) this._cacheability]) 
    return; 
    this.Dirtied(); 
    this._cacheability = cacheability; 
} 

换句话说,如果你设置NoCache的第一个(值1),它总是如果您尝试设置较高的值,例如4(公共),则返回。

唯一的办法是到餐桌的项目,它向你如何要求,或者发送pull请求,以纪念protected ICacheHeadersHelper CacheHeadersHelperDonutOutputCacheAttribute

1

您可以从版式视图中的AJAX调用,甚至跟踪访问者如果页面被缓存。这就是Google Analytics所做的。我建议从布局视图执行它,因为它将在所有使用该布局的视图中执行。 还有一点评论,假设您有两个布局视图:一个用于网站的公共部分,另一个用于后端(仅限员工)。您可能有兴趣跟踪用户,而不是员工,所以这是在Layout View进行跟踪的另一个好处。如果将来您想跟踪员工正在做什么,则可以为后端布局视图添加一个不同的跟踪器。 我希望它有帮助。