我已将Output Caching添加到我的应用程序中的几个操作中,以便轻松提升性能。但是,这些操作还需要在每个请求(它是一个视图计数器)之后通过命中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);
}
}
不,也没用;缓存操作后,操作过滤器似乎完全被忽略。游民。
所以,呃,有没有办法(没有实现自定义输出缓存提供程序),以确保我的观点被正确计算,干净,明智?
该 OutputCacheAttribute
顺便提一下,有一个名为的自定义属性 DonutOutputCache 由Paul Hiles开发,有助于克服这些局限。
它支持的一个重要功能是,您可以拥有一个可以一直调用的动作过滤器,即使动作是否标记有缓存属性。
对于前者您希望缓存一个持续5秒的操作,同时您希望每次操作使用a收到请求时进行记录 LogThis
过滤器可以通过以下方式实现
[LogThis]
[DonutOutputCache(Duration=5, Order=100)]
public ActionResult Index()
从 保罗,
是的,与内置的OutputCacheAttribute不同,动作过滤器会
即使从缓存中检索页面也会执行。唯一的警告
添加是你需要注意过滤顺序。如果
您的操作过滤器实现OnResultExecuting或OnResultExecuted
然后这些方法将在所有情况下执行,但是
OnActionExecuting和OnActionExecuted,只有在执行时才会执行
过滤器在DonutOutputCacheAttribute之前运行。这是因为
MVC阻止后续过滤器执行的方式
设置filterContext.Result属性,这是我们需要做的
输出缓存。
我不认为你可以依赖于哪个动作过滤器的顺序
在动作或控制器上定义。确保一个过滤器运行
在另一个之前,您可以使用存在的Order属性
在所有ActionFilterAttribute实现上。没有的任何行动
order属性集,默认值为-1,表示它们将
在具有显式Order值的过滤器之前执行。
因此,在您的情况下,您只需添加Order = 100即可
DonutOutputCache属性和所有其他过滤器将在之前执行
缓存过滤器。
该 OutputCacheAttribute
顺便提一下,有一个名为的自定义属性 DonutOutputCache 由Paul Hiles开发,有助于克服这些局限。
它支持的一个重要功能是,您可以拥有一个可以一直调用的动作过滤器,即使动作是否标记有缓存属性。
对于前者您希望缓存一个持续5秒的操作,同时您希望每次操作使用a收到请求时进行记录 LogThis
过滤器可以通过以下方式实现
[LogThis]
[DonutOutputCache(Duration=5, Order=100)]
public ActionResult Index()
从 保罗,
是的,与内置的OutputCacheAttribute不同,动作过滤器会
即使从缓存中检索页面也会执行。唯一的警告
添加是你需要注意过滤顺序。如果
您的操作过滤器实现OnResultExecuting或OnResultExecuted
然后这些方法将在所有情况下执行,但是
OnActionExecuting和OnActionExecuted,只有在执行时才会执行
过滤器在DonutOutputCacheAttribute之前运行。这是因为
MVC阻止后续过滤器执行的方式
设置filterContext.Result属性,这是我们需要做的
输出缓存。
我不认为你可以依赖于哪个动作过滤器的顺序
在动作或控制器上定义。确保一个过滤器运行
在另一个之前,您可以使用存在的Order属性
在所有ActionFilterAttribute实现上。没有的任何行动
order属性集,默认值为-1,表示它们将
在具有显式Order值的过滤器之前执行。
因此,在您的情况下,您只需添加Order = 100即可
DonutOutputCache属性和所有其他过滤器将在之前执行
缓存过滤器。
即使页面已缓存,您也可以从布局视图进行AJAX调用并跟踪访问者。这就是Google Analytics所做的事情。我建议从布局视图中执行此操作,因为它将在使用该布局的所有视图中执行。
还有一个评论,假设您有两个布局视图:一个用于站点的公共部分,另一个用于后端(仅限员工)。您可能对跟踪用户而不是员工感兴趣,因此这是在布局视图中跟踪的另一个好处。如果将来您想要跟踪员工正在做什么,您可以为后端布局视图添加不同的跟踪器。
我希望它有所帮助。
原因实际上是在.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(公共)),它将始终返回。
唯一的解决方案是分叉项目并将其扩展到您需要的方式,或者发送拉取请求以进行标记 protected ICacheHeadersHelper CacheHeadersHelper
在 DonutOutputCacheAttribute