在项目使用OutputCacheAttribute是遇到了问题,当我想在配置文件web.config中配置OutputCache的VaryByParam时竟然不起作用,下面是相关代码:

文件FaceController.cs

    [OutputCache(CacheProfile = "faceProfile")]
public ActionResult Index()
{
return View();
}

文件index.cshtml

<h2>@DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")</h2>

web.config的cache配置

  <system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="faceProfile" duration ="180" varyByParam="none" enabled="true"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
<system.web>

下面是我的测试:

请求 /face/index 页面,输出: 2014-08-02 18:40:56.184

再次请求 /face/index 页面,输出: 2014-08-02 18:40:56.184 (不变)

因为我指定了varyByParam="none",所以我添加参数或改变参数,输出的时间应该不变才对,可是:

请求 /face/index/?p=19999 页面,输出: 2014-08-02 18:42:29.720 (变了)

请求 /face/index/?p=10000 页面,输出: 2014-08-02 18:43:30.981 (变了)

请求 /face/index/?abcd 页面,输出: 2014-08-02 18:44:00.440 (变了)

请求结果随着参数的变化而变化,所以它应该是为每个参数都缓存了一个版本相当于设置了varyByParam="*"

从测试结果可以看出配置文件中设置的duration ="180"有起到作用,而varyByParam="none"没有起到作用.

然后我试着把varyByParam="none"直接写到代码里:

    [OutputCache( Duration=180,VaryByParam="none")]
public ActionResult Index()
{
return View();
}

这次结果它正确进行缓存页面,没有为每个参数缓存一个版本,这使我很困惑,然后我看了一下OutputCacheAttribute的源码,这里我贴出的是部分关键源码:

public class OutputCacheAttribute : ActionFilterAttribute, IExceptionFilter
{ private OutputCacheParameters _cacheSettings = new OutputCacheParameters { VaryByParam = "*" };
//_cacheSettings中的每个属性都以 CacheProfile 属性的方式再包装了一遍
//其余类似的属性我就不贴出来了
public string CacheProfile
{
get{return _cacheSettings.CacheProfile ?? String.Empty; }
set{_cacheSettings.CacheProfile = value;}
}
//省去了无关代码
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
//省去了无关代码 using (OutputCachedPage page = new OutputCachedPage(_cacheSettings))
{
page.ProcessRequest(HttpContext.Current);
}
}
private sealed class OutputCachedPage : Page
{
private OutputCacheParameters _cacheSettings;
public OutputCachedPage(OutputCacheParameters cacheSettings)
{
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
_cacheSettings = cacheSettings;
}
protected override void FrameworkInitialize()
{
// when you put the <%@ OutputCache %> directive on a page, the generated code calls InitOutputCache() from here
base.FrameworkInitialize();
InitOutputCache(_cacheSettings);
}
}
}

由上面的代码可以看出_cacheSettings根本就没从配置文件里读取,而是直接由 OutputCache( Duration=180,VaryByParam="none") 这样设置进去的,然后直接传人Page.InitOutputCache(cacheSettings)中,可见它直接使用asp.net以前的方式OutputCacheModule来实现缓存的,InitOutputCache中应该有去加载配置里面的设置, 然后看看cacheSettings的相应字段是否已经有合适的值了,如果没有则使用配置里边的值。而我们在使用OutputCache时,如果没有传人VaryByParam值,则它默认的值就为"*"(从cacheSettings初始化时看出来的) 。故代码:

    [OutputCache(CacheProfile = "faceProfile")]
public ActionResult Index()
{
return View();
}

相当于

    [OutputCache(CacheProfile = "faceProfile",VaryByParam = "*")]
public ActionResult Index()
{
return View();
}

配置里的VaryByParam的值是不会覆盖代码里面的VaryByParam的值的,所以才会出现我们测试时,对每个参数都进行缓存的情况。

解决办法:

  1. 把VaryByParam 就直接写入代码, 其他的参数在配置中来完成如:OutputCache(CacheProfile = "faceProfile", VaryByParam = "none")
  2. 自己实现一个OutputCacheAttritube

    下面就是我把OutputCacheAttritube源码做一些修改后满足自己需求的MySimpleCacheAttribute,不过它不适用于ChildAction,但我可以在配置文件中控制VaryByParam参数,改造后的代码如下:
namespace Mvc.Cache
{
using System.Web.Mvc;
using System.Web.UI;
using System;
using System.Web;
public class MySimpleCacheAttribute : ActionFilterAttribute
{
private OutputCacheParameters _cacheSettings = new OutputCacheParameters();
public MySimpleCacheAttribute()
{
}
public string CacheProfile
{
get
{
return _cacheSettings.CacheProfile ?? String.Empty;
}
set
{
_cacheSettings.CacheProfile = value;
}
} internal OutputCacheParameters CacheSettings
{
get
{
return _cacheSettings;
}
}
public int Duration
{
get
{
return _cacheSettings.Duration;
}
set
{
_cacheSettings.Duration = value;
}
}
public OutputCacheLocation Location
{
get
{
return _cacheSettings.Location;
}
set
{
_cacheSettings.Location = value; }
}
public bool NoStore
{
get
{
return _cacheSettings.NoStore;
}
set
{
_cacheSettings.NoStore = value; }
}
public string SqlDependency
{
get
{
return _cacheSettings.SqlDependency ?? String.Empty;
}
set
{
_cacheSettings.SqlDependency = value;
}
}
public string VaryByContentEncoding
{
get
{
return _cacheSettings.VaryByContentEncoding ?? String.Empty;
}
set
{
_cacheSettings.VaryByContentEncoding = value;
}
}
public string VaryByCustom
{
get
{
return _cacheSettings.VaryByCustom ?? String.Empty;
}
set
{
_cacheSettings.VaryByCustom = value;
}
}
public string VaryByHeader
{
get
{
return _cacheSettings.VaryByHeader ?? String.Empty;
}
set
{
_cacheSettings.VaryByHeader = value;
}
}
public string VaryByParam
{
get
{
return _cacheSettings.VaryByParam ?? String.Empty;
}
set
{
_cacheSettings.VaryByParam = value;
}
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.IsChildAction)
{
using (OutputCachedPage page = new OutputCachedPage(_cacheSettings))
{
page.ProcessRequest(HttpContext.Current);
}
}
}
private sealed class OutputCachedPage : Page
{
private OutputCacheParameters _cacheSettings; public OutputCachedPage(OutputCacheParameters cacheSettings)
{
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
_cacheSettings = cacheSettings;
} protected override void FrameworkInitialize()
{
base.FrameworkInitialize();
InitOutputCache(_cacheSettings);
}
}
}
}

使用:

    [MySimpleCache(CacheProfile = "faceProfile")]
public ActionResult Index()
{
return View();
}

MVC中配置OutputCache的VaryByParam参数无效的问题的更多相关文章

  1. 【已解决】React中配置Sass引入.scss文件无效

    React中配置Sass引入.scss文件无效 在react中使用sass时,引入.scss文件失效 尝试很多方法没法解决,最终找到解决方法,希望能帮助正在坑里挣扎的筒子~ 在node_modules ...

  2. MVC中URL传多个参数

    1.mvc中url传递多个参数不能直接使用&,会报错(从客户端(&)中检测到有潜在危险的 Request.Path 值) 方法①:使用?---/Home/Index/?id=xxx&a ...

  3. React中配置Sass引入.scss文件无效

    React中配置Sass引入.scss文件无效 在react中使用sass时,引入.scss文件失效尝试很多方法没法解决,最终找到解决方法,希望能帮助正在坑里挣扎的筒子~ 在node_modules文 ...

  4. 在Asp.Net MVC 中配置 Serilog

    Serilog 是一种非常简便记录log 的处理方式,使用Serilog可以生成本地的text文件, 也可以通过 Seq 来在Web界面中查看具体的log内容. 接下来就简单的介绍一下在Asp.Net ...

  5. MVC中的奇葩错误,参数转对象

    在使用MVC中遇到一个神奇的错误,特此记录(我在用MVC4时遇到) 上面两张图就是一个变量名进行了修改,其他不变!form里面的参数也是一样的!喜欢尝试的可以尝试一下! 我的变量使用action时出现 ...

  6. 获取MVC中Controller下的Action参数异常

    我现在做的一个项目有一个这样的需求, 比如有一个页面需要一个Guid类型的参数: public ActionResult Index(Guid id) { //doing something ... ...

  7. mvc中的OutputCache

    mvc4中有一个标记属性OutputCache,用来对ActionResult结果进行缓存,如何理解呢?概括地说,就是当你的请求参数没有发生变化时,直接从缓存中取结果,不会再走服务端的Action代码 ...

  8. 在Spring MVC 中配置自定义的类型转换器

    方法一: 实现spring mvc 自带的 Formatter 接口 1.创建一个类来实现Formatter接口 import org.springframework.format.Formatter ...

  9. Asp.net MVC中文件上传的参数转对象的方法

    参照博友的.NET WebApi上传文件接口(带其他参数)实现文件上传并带参数,当需要多个参数时,不想每次都通过HttpContext.Request.Params去取值,就针对HttpRequest ...

随机推荐

  1. table行转列

    table行转列 摘要 在使用ews调用exhange的收件箱的并在h5页面显示邮件详情的时候,因为返回的每封邮件的内容都是htmlbody,没有textbody.每封邮件又没什么规律,用正则表达式来 ...

  2. C语言实现OOP 版本2

    写版本2的原因,还是发现在不同的具体图形模块里发现了重复的release代码,这是坏味道,所以还是决定消除这些重复代码,DRY! shape.h #ifndef SHAPE_H #define SHA ...

  3. 《Programming WPF》翻译 第3章 3.内嵌控件

    原文:<Programming WPF>翻译 第3章 3.内嵌控件 WPF提供了一系列内嵌控件.其中大多数符合标准的你已经熟悉的Windows控件类型.注意到没有一个是包装在旧的Win32 ...

  4. 转:PHP的(Thread Safe与Non Thread Safe)

    在安装xdebug到时候你会有有TS和NTS版本的选择,在以前还有VC6和VC9的版本.如果你没有根据你目前的服务器的状况选择对应的版本的话,那么xdebug是安装不成功的. 一.如何选择 php5. ...

  5. 2015第14周日WebSocket

    清明时节雨纷纷,路上行人欲断魂,借问酒家何处是?牧童遥指杏花村.每次清明都不禁想起杜牧这首诗缅怀先人,此时第一句写时间天气,第二句写人物心情,第三句写解决方法,第四句给出解决方案,脍炙人口. 刚没事看 ...

  6. C++ builder 生成以管理员身份运行的exe

    转自:http://bbs.csdn.net/topics/310225109#post-312177603 ,稍微做了一点修改 创建一个文本文件,命名为123.manifest,内容如下: < ...

  7. 网站10大致命SEO错误

    1.关键字堆砌 我想不出有比胡乱将这些复制的内容放在网站上更差劲的事情了.网站复制一遍又一遍,你肯定也不想看到这么差劲的网站复制. 你在明白我在做什么吗?我并不是一个那么差劲的编辑者,我只是想说明一个 ...

  8. java 实现排序

    package com.cjs.sort; /** * 此类用来提供针对整数的各种排序算法 * * @author S * @version 1.0 */ public class MySort { ...

  9. errno的基本用法

    error是一个包含在 perror()和strerrot()函数可以把errno的值转化为有意义的字符输出. #include <stdio.h> #include <stdlib ...

  10. 【转】Linux系统性能分析命令

    作为一名linux系统管理员,最主要的工作是优化系统配置,使应用在系统上以最优的状态运行,但是由于硬件问题.软件问题.网络环境等的复杂性和多变性,导致对系统的优化变得异常复杂,如何定位性能问题出在哪个 ...