最近给SpaceBuilder增加OutputCache 时发现了一些问题,贴在这做个备忘,也方便遇到类似问题的朋友查阅。

目前SpaceBuilder表现层使用是asp.net mvc v1.0,使用了很多RenderAction(关于asp.net mvc的Partial Requests参见Partial Requests in ASP.NET MVC)。希望对于实时性要求不高的内容区域采用客户端缓存来提升性能同时也弥补一下RenderAction对性能的损失。

使用asp.net mvc自带的OutputCache Filter时发现了一个可怕的bug,在View中任何一个RenderAction设置OutputCache却影响了整个View。搜索发现确实是asp.net mvc目前已知的一个bug ,关于该问题的解决也有很多人提出了自己的方法。

关于asp.net mvc的缓存,Haacked写了两篇文章:

Donut Caching in ASP.NET MVC 介绍的是缓存整个页面,对于一部分内容禁用缓存,是在mvc中实现的WebForm的Substitution功能。存在以下弊端:当前一个View中有多个区域需要禁用缓存时使用比较麻烦,另外不能实现对页面的不同的区域使用不同的过期策略。

Donut Hole Caching in ASP.NET MVC介 绍的是我想要的功能,即只缓存页面的部分区域。但是弊端也非常明显:只能通过WebForm中的声明方式来使用用户控件(:),现在已经有点不适应这种方 式了,而且必须使用WebFormViewEngine),无法直接使用RenderPartial,而且还必须设置强类型的ViewPage,确保在用 户控件中的Model与View中的Model相同。使用太麻烦,限制也多。

Maarten Balliauw在 Creating an ASP.NET MVC OutputCache ActionFilterAttributeExtending ASP.NET MVC OutputCache ActionFilterAttribute - Adding substitution   也提出了一个完整的OutputCache解决方案。但是经测试启用客户端缓存时同样会产生与RenderAction同样的问题,还没有时间彻查这个问题,先把客户端缓存禁用,暂时使用服务器端缓存应付一阵。

以Maarten Balliauw的代码为原型,编写了SpaceBuilder的ActionOutputCacheAttribute:


    publicclass ActionOutputCacheAttribute : ActionFilterAttribute     {         privatestatic MethodInfo _switchWriterMethod =typeof(HttpResponse).GetMethod("SwitchWriter", BindingFlags.Instance | BindingFlags.NonPublic);          public ActionOutputCacheAttribute(int cacheDuration)         {             _cacheDuration = cacheDuration;         }          //目前还不能设置为Client缓存,会与OutputCache同样的问题         private CachePolicy _cachePolicy = CachePolicy.Server;         privateint _cacheDuration;         private TextWriter _originalWriter;         privatestring _cacheKey;          publicoverridevoid OnActionExecuting(ActionExecutingContext filterContext)         {             // Server-side caching?             if (_cachePolicy == CachePolicy.Server || _cachePolicy == CachePolicy.ClientAndServer)             {                 _cacheKey = GenerateCacheKey(filterContext);                 CacheContainer cachedOutput = (CacheContainer)filterContext.HttpContext.Cache[_cacheKey];                 if (cachedOutput !=null)                 {                     filterContext.HttpContext.Response.ContentType = cachedOutput.ContentType;                     filterContext.Result =new ContentResult { Content = cachedOutput.Output };                 }                 else                 {                     StringWriter stringWriter =new StringWriterWithEncoding(filterContext.HttpContext.Response.ContentEncoding);                     HtmlTextWriter newWriter =new HtmlTextWriter(stringWriter);                     _originalWriter = (TextWriter)_switchWriterMethod.Invoke(HttpContext.Current.Response, newobject[] { newWriter });                 }             }         }          publicoverridevoid OnResultExecuted(ResultExecutedContext filterContext)         {             // Server-side caching?             if (_cachePolicy == CachePolicy.Server || _cachePolicy == CachePolicy.ClientAndServer)             {                 if (_originalWriter !=null) // Must complete the caching                 {                     HtmlTextWriter cacheWriter = (HtmlTextWriter)_switchWriterMethod.Invoke(HttpContext.Current.Response, newobject[] { _originalWriter });                     string textWritten = ((StringWriter)cacheWriter.InnerWriter).ToString();                     filterContext.HttpContext.Response.Write(textWritten);                     CacheContainer container =new CacheContainer(textWritten, filterContext.HttpContext.Response.ContentType);                     filterContext.HttpContext.Cache.Add(_cacheKey, container, null, DateTime.Now.AddSeconds(_cacheDuration), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);                 }             }         }          privatestring GenerateCacheKey(ActionExecutingContext filterContext)         {             StringBuilder cacheKey =new StringBuilder("OutputCacheKey:");              // Controller + action             cacheKey.Append(filterContext.Controller.GetType().FullName.GetHashCode());             if (filterContext.RouteData.Values.ContainsKey("action"))             {                 cacheKey.Append("_");                 cacheKey.Append(filterContext.RouteData.Values["action"].ToString());             }              foreach (KeyValuePair<string, object> pair in filterContext.ActionParameters)             {                 cacheKey.Append("_");                 cacheKey.Append(pair.Key);                 cacheKey.Append("=");                  if (pair.Value !=null)                     cacheKey.Append(pair.Value.ToString());                 else                     cacheKey.Append(string.Empty);             }              return cacheKey.ToString();         }          privateclass CacheContainer         {             publicstring Output;             publicstring ContentType;             public CacheContainer(string data, string contentType)             {                 Output = data;                 ContentType = contentType;             }         }          publicenum CachePolicy         {             NoCache =,             Client =,             Server =,             ClientAndServer =         }     }

    { encoding;        

StringWriterWithEncoding     publicclass StringWriterWithEncoding : StringWriter     {         Encoding encoding;         public StringWriterWithEncoding(Encoding encoding)         {             this.encoding = encoding;         }         publicoverride Encoding Encoding         {             get{ return encoding; }         }     }

转自:http://www.cnblogs.com/mazq/archive/2009/05/30/1492298.html

asp.net mvc Partial OutputCache 在SpaceBuilder中的应用实践的更多相关文章

  1. Asp.net mvc web api 在项目中的实际应用

    Asp.net mvc web api 在项目中的实际应用 前言:以下只是记录本人在项目中的应用,而web api在数据传输方面有多种实现方式,具体可根据实际情况而定! 1:数据传输前的加密,以下用到 ...

  2. 在Asp.net MVC 3 web应用程序中,我们会用到ViewData与ViewBag,对比一下:

    Asp.net MVC中的ViewData与ViewBag ViewData ViewBag 它是Key/Value字典集合 它是dynamic类型对像 从Asp.net MVC 1 就有了 ASP. ...

  3. ASP.NET MVC 学习8、Controller中的Detail和Delete方法

    参考:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-details-and ...

  4. ASP.NET MVC 学习4、Controller中添加SearchIndex页面,实现简单的查询功能

    参考:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-method ...

  5. [小技巧][ASP.Net MVC Hack] 使用 HTTP 报文中的 Header 字段进行身份验证

    在一些 Web 系统中,身份验证是依靠硬件证书进行的:在电脑上插入 USB 证书,浏览器插件读取证书的相关信息,然后在发送 HTTP 登录请求时顺便在 Header 字段附加上身份信息.服务器端处理这 ...

  6. [转]Load ASP.NET MVC Partial Views Dynamically Using jQuery

    本文转自:http://www.binaryintellect.net/articles/218ca630-ba50-48fe-af6e-6f754b5894aa.aspx Most of the t ...

  7. ASP.NET MVC Partial页输出JS

    很多情况Partial是需要引用到JS的,通常做法是吧JS在引用Partial的页面中加入JS文件或者JS代码. 前阵子网上看到一段代码可以在Partial页面中添加JS,输出道引用页面. publi ...

  8. ASP.NET MVC系列:web.config中ConnectionString aspnet_iis加密与AppSettings独立文件

    1. web.config中ConnectionString aspnet_iis加密 web.config路径:E:\Projects\Libing.Web\web.config <conne ...

  9. ASP.NET MVC做的微信WEBAPP中调用微信JSSDK扫一扫

    今天做一个项目,是在微信上用的,微信WEB APP,里面用到了调用手机摄像头扫一扫二维码的功能,记得以前某个项目里写有的,但是找不到之前那个项目源码了,想复制粘贴也复制不了了,只好对着微信的那个开发文 ...

随机推荐

  1. Property Animator基本用法

    ObjectAnimator anim=ObjectAnimator.ofFloat(textview, "alpha", 0f, 1f); //ObjectAnimator an ...

  2. 关于js sort排序方法

    sort() 方法用于对数组的元素进行排序. 语法:arrayObject.sort(sortby):参数sortby可选.规定排序顺序.必须是函数. 当方法不带参数的时候,将按照字符编码顺序进行排序 ...

  3. androidAndroid开发学习--Ionic+Cordova 环境搭建

    我们看 Ionic 能给我们提供什么?  一个样式库,你可以使用它 来 装饰你的 HTML 网页 ,看起来 想 移动程序的 界面,什么 header .content.footer.grid.list ...

  4. Asp.Net网站统一处理错误信息

    1.创建Global.asax文件 2.在Application_Error里统一处理,可以写入文件,也可以写入SQL.代码如下 Exception ex = Server.GetLastError( ...

  5. DHTMLTree、Dtree和Ztree的学习使用

    一.DHTMLTree是树菜单,允许我们快速开发界面优美,基于Ajax的javascript库.她允许在线编辑,拖拽,三种状态(全选.不选.半选),复选框等模式.同时在加载大数据量的时候,仍然可以保持 ...

  6. linux中什么是文件结构体?

    struct file结构体定义在include/linux/fs.h中定义.文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file.它由内核在打开文件时 ...

  7. P1393 动态逆序对

    题目 P1393 动态逆序对 做题前写篇博客是个好方法 做法 题目规定仅有删除,给每个位置标个号,逆序对+时间轴,显然这是个三维偏序 很久没做过\(cdq\)了,就当模板题讲一下: 按删除的先后顺序为 ...

  8. sqlserver 2008 创建数据库的时候不是空库,里面总有数据的解决办法

    SqlServer2008 里面有个系统数据库 Model 数据库,在创建新数据库的时候,会以它为模板创建,所以如果发现你的Model数据库比较大,说明里面有很多模板数据.此时如果需要去创建没有数据的 ...

  9. Jquery Uploadify多文件上传实例

    jQuery Uploadify开发使用的语言是java. 详细的相关文档,可以参考官网的doc:http://www.uploadify.com/documentation/ 官网的讲解还是很详细的 ...

  10. ubantu卸载软件

    参考:https://blog.csdn.net/luckydog612/article/details/80877179 https://blog.csdn.net/get_set/article/ ...