为特定控制器操作选择自定义输出缓存提供程

我正在尝试实现MongoDB / Memory组合输出缓存提供程序以与MVC4一起使用。 这是我最初的实现:

public class CustomOutputCacheProvider : OutputCacheProvider { public override object Get(string key) { FileLogger.Log(key); return null; } public override object Add(string key, object entry, DateTime utcExpiry) { return entry; } public override void Set(string key, object entry, DateTime utcExpiry) { } public override void Remove(string key) { } } 

我的网络配置条目:

        

以及HomeController中的用法:

 [OutputCache(Duration = 15)] public ActionResult Index() { return Content("Home Page"); } 

我的问题是,当我检查日志文件中所请求的密钥时,我不仅看到了对主控制器的请求,还看到了所有其他路径:

 a2/ <-- should only log this entry a2/test a2/images/test/50115c53/1f37e409/4c7ab27d/50115c531f37e4094c7ab27d.jpg a2/scripts/jquery-1.7.2.min.js 

我想我不应该将CustomOutputCacheProvider设置为Web.Config中的defaultProvider,我无法弄清楚如何指定我想用于特定控制器操作的缓存提供程序。

使用Asp.Net网页,您可以通过在页面顶部使用来完成它,但对于MVC,我能找到的唯一解决方案是覆盖Global.asax中的HttpApplication.GetOutputCacheProviderName方法 。

有没有更优雅的方法来实现这一点,使用[OutputCache]属性?

是否有更优雅的方法使用[OutputCache]属性设置OutputCacheProvider?

我认为答案是否定的(当前mvc4版本没有),因为实现自定义OutputCacheProvider和使用OutputCache属性修饰操作之间没有任何关系。

正如您通过实现自定义提供程序并登录 Get方法所发现的那样,您会看到对Web服务器发出的每个请求。 如果要从所有操作中删除OutputCache属性,您仍将在out日志文件中看到每个请求。 我认为这个ASP.NET MVC的答案会针对每个动作点击outputcache,这对于确认它是非常有用的。

由于看起来您只想实现一个输出缓存提供程序,因此我认为您唯一的选择是设置默认提供程序并继续覆盖GetOutputCacheProviderName实现(如您所述)。 也许是这样的,以排除所有内容图像脚本

 public override string GetOutputCacheProviderName(HttpContext context) { string absolutePath = context.Request.Url.AbsolutePath; if (absolutePath.StartsWith("/Content/", StringComparison.CurrentCultureIgnoreCase) || absolutePath.StartsWith("/Scripts/", StringComparison.CurrentCultureIgnoreCase) || absolutePath.StartsWith("/Images/", StringComparison.CurrentCultureIgnoreCase)) return base.GetOutputCacheProviderName(context); return "CustomOutputCacheProvider"; } 

如果您需要实现多个输出缓存提供程序,那么我猜您必须实现一个帮助程序才能为您提供正确的提供程序名称。 但这是一个我为你解决了路由数据的例子; prev例如直接看url。

 public override string GetOutputCacheProviderName(HttpContext context) { RouteCollection rc = new RouteCollection(); MvcApplication.RegisterRoutes(rc); RouteData rd = rc.GetRouteData(new HttpContextWrapper(HttpContext.Current)); if (rd == null) return base.GetOutputCacheProviderName(context); var controller = rd.Values["controller"].ToString(); var action = rd.Values["action"].ToString(); if (controller.Equals("Content", StringComparison.CurrentCultureIgnoreCase) || controller.Equals("Scripts", StringComparison.CurrentCultureIgnoreCase) || controller.Equals("Images", StringComparison.CurrentCultureIgnoreCase)) return base.GetOutputCacheProviderName(context); if (controller.Equals("Account", StringComparison.CurrentCultureIgnoreCase)) return "AccountOutputCacheProvider"; if (controller.Equals("Something", StringComparison.CurrentCultureIgnoreCase)) return controller + "OutputCacheProvider"; return "CustomOutputCacheProvider"; } 

如果我在哪里,我会尝试编写inheritance自OutputCachAttribute的MyOutputCachAttribute,它将通过其参数选择provider。

查看MSDN杂志上的这篇文章(源代码和示例引用MongoDB和Azure作为分布式缓存提供程序)可能会提供一些见解http://msdn.microsoft.com/en-us/magazine/gg650661.aspx

编辑

您是否可以使用CacheProfile设置来指定此处建议的提供程序?

http://www.dotnetcurry.com/ShowArticle.aspx?ID=665