c# - 为特定 Controller 操作选择自定义输出缓存提供程序

标签 c# asp.net caching asp.net-mvc-4

我正在尝试实现一个 MongoDB/内存组合输出缓存提供程序以与 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)
    {
    }
}

还有我的网络配置条目:

<caching>
  <outputCache defaultProvider="CustomOutputCacheProvider">
    <providers>
      <add name="CustomOutputCacheProvider" type="MyApp.Base.Mvc.CustomOutputCacheProvider" />
    </providers>
  </outputCache>
</caching>

以及 HomeController 中的用法:

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

我的问题是,当我检查所请求 key 的日志文件时,我不仅看到了对家庭 Controller 的请求,还看到了所有其他路径:

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,我想不通的是如何指定我想用于特定 Controller 操作的缓存提供程序。

对于 Asp.Net 网页,您可以使用 <%@ OutputCache Duration="60" VaryByParam="None" providerName="DiskCache" %> 来完成它在页面顶部,但对于 MVC,我能找到的唯一解决方案是覆盖 HttpApplication.GetOutputCacheProviderName Method在 Global.asax 中。

是否有更优雅的方法通过使用 [OutputCache] 属性来完成此操作?

最佳答案

Is there a more elegant way to set the OutputCacheProvider using the [OutputCache] attribute?

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

正如您通过在 Get 方法中实现自定义提供程序和日志记录 所发现的那样,您会看到对 Web 服务器发出的每个请求。如果您要从所有操作中删除 OutputCache 属性,您仍会在输出日志文件中看到每个请求。我想到了这个 ASP.NET MVC hits outputcache for every action 的答案对确认这一点非常有用。

因为看起来您只想实现一个输出缓存提供程序,所以我认为您唯一的选择是设置默认提供程序并继续覆盖 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";
}

如果您需要实现多个输出缓存提供程序,那么我想您必须实现一个助手来为您提供正确的提供程序名称。但这里有一个例子,我已经为你解决了路由数据;上一个示例直接查看 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";
}

关于c# - 为特定 Controller 操作选择自定义输出缓存提供程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11818528/

相关文章:

c# - Ninject.ActivationException : Error activating IMainLicense 错误

c# - 窗口加载和 WPF

c# - 如何将 ef4 上下文或至少某些实体还原为其原始值?

node.js - 动态数据 Express.JS 的缓存控制

c# - 未实现接口(interface)成员 'System.ComponentModel.INotifyPropertyChanged.PropertyChanged'

c# - 正则表达式获取自定义TAG之间的所有值

asp.net - 您无权查看此目录或页面。 Azure Web API

javascript - 随着时间增量动态创建表

asp.net - 缓存以便稍后写入 ASP.NET Web 服务中的数据库?

caching - 我如何使用缓存控制和 ETag 来设置 http header