Asp.Net MVC页面静态化功能实现一:利用IHttpModule和ResultFilter
由于公司现在所采用的是一套CMS内容管理系统的框架,所以最近项目中有一个需求提到要求实现页面静态化的功能。在网上查询了一些资料和文献,最后采用的是小尾鱼的池塘提供的 利用ResultFilter实现asp.net mvc3 页面静态化实现方式,然后结合IHttpModule过滤并判断当前请求。实现代码如下:
实现思路:当服务器接收到一条Http请求后,会先进入IHttpModule并分析出当前请求的Url对应的静态页面文件路径。如果该文件存在,直接返回静态页面给客户端,终止本次请求。如果静态页面不存在,则通过路由进入对应的Controller和Action,在服务器即将将html代码返回给客户端的时候,捕获html代码,并保存为html文件。
一、 添加一个自定义一个筛选器
1、定义一个类WriteHtmlAttributeWrapper,该类继承自Stream。该代码主要是实现了重写Write方法,将Response.Filter中流的数据保存为html文件(Response.Filter包含即将返回给本次请求客户端的html代码)。
/// <summary>
/// 重写筛选器,将返回客户端的html代码保存到本地文件
/// </summary>
/// <remarks>
/// 作者: Traicne
/// 时间: 2015-10-19
/// </remarks>
public class WriteHtmlAttributeWrapper : System.IO.Stream
{
private System.IO.Stream inner;
private ControllerContext context;
public WriteHtmlAttributeWrapper(System.IO.Stream s, ControllerContext context)
{
this.inner = s;
this.context = context;
} public override bool CanRead
{
get { return inner.CanRead; }
} public override bool CanSeek
{
get { return inner.CanSeek; }
} public override bool CanWrite
{
get { return inner.CanWrite; }
} public override void Flush()
{
inner.Flush();
} public override long Length
{
get { return inner.Length; }
} public override long Position
{
get { return inner.Position; }
set { inner.Position = value; }
} public override int Read(byte[] buffer, int offset, int count)
{
return inner.Read(buffer, offset, count);
} public override long Seek(long offset, System.IO.SeekOrigin origin)
{
return inner.Seek(offset, origin);
} public override void SetLength(long value)
{
inner.SetLength(value);
} public override void Write(byte[] buffer, int offset, int count)
{
inner.Write(buffer, offset, count);//当前请求不是后台管理;并且返回客户端是html才生成静态页面
if (!context.HttpContext.Request.FilePath.ToLower().StartsWith("/admin") && context.HttpContext.Response.ContentType.Equals("text/html"))
{
//静态页面保存路径信息
string htmlPath = context.HttpContext.Request.HtmlFilePath();
string direcHtmlPath = Path.GetDirectoryName(htmlPath);
if (!Directory.Exists(direcHtmlPath))
{
Directory.CreateDirectory(direcHtmlPath);
}
//获取返回客户端的html代码,并进行压缩处理
string htmlCode = System.Text.Encoding.UTF8.GetString(buffer);
htmlCode = Regex.Replace(htmlCode, "^\\s*", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
htmlCode = Regex.Replace(htmlCode, "\\r\\n", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
htmlCode = Regex.Replace(htmlCode, "<!--*.*?-->", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
//保存文件,这里不能用File.WriteAllText
File.AppendAllText(htmlPath, htmlCode);
}
}
}
2、添加一个自定义类WriteHtmlAttribute,该类继承自FilterAttribute, IResultFilter。
/// <summary>
/// 自定义筛选器
/// </summary>
/// <remarks>
/// 作者: Traicne
/// 时间: 2015-10-19
/// </remarks>
public class WriteHtmlAttribute : FilterAttribute, IResultFilter
{
/// <summary>
/// 在操作结果执行后调用
/// </summary>
public void OnResultExecuted(ResultExecutedContext filterContext)
{
//当View()中存在@Html.Action时,会出现“不允许进行筛选”的错误,这时需要判断当前Filter是否为空
//当Action中存在重定向RedirectToAction时,会出现“Object Move To Here”的错误信息,这时需要判断当前返回给客户端的状态码
//if (filterContext.HttpContext.Response.Filter != null)
if (filterContext.HttpContext.Response.Filter != null && filterContext.HttpContext.Response.StatusCode.Equals())
{
//重写筛选器对象
filterContext.HttpContext.Response.Filter = new WriteHtmlAttributeWrapper(filterContext.HttpContext.Response.Filter, filterContext);
}
} /// <summary>
/// 在操作结果执行之前调用
/// </summary>
public void OnResultExecuting(ResultExecutingContext filterContext)
{ }
}
该类有两点点需要注意的地方
第一:需要对filterContext.HttpContext.Response.Filter是否为Null的判断。因为当你的Action返回的视图View()中存在子Action时,OnResultExecuted()会被执行多次(自定义筛选器WriteHtmlAttribute是对于每一个Action都有效)
第二:需要对返回给客户端的状态码做一个判断,即filterContext.HttpContext.Response.StatusCode.Equals(200)。因为当的Action中存在某个重定向操作RedirectToAction到另外一个Action的时候,会出现重定向到的页面出现“Object Move To Here”这样的内容信息。
3、添加自定义筛选器
添加自定义筛选器可以在Global.asax文件的Application_Start方法中添加,也可以在FilterConfig类中的RegisterGlobalFilters方法中添加。二者都是向GlobalFilterCollection中添加一个筛选器,都是一样的效果。
//FilterConfig类中的RegisterGlobalFilters方法中添加如下代码
filters.Add(new WriteHtmlAttribute());
//或者在Global.asax文件Application_Start方法添加这段代码
GlobalFilters.Filters.Add(new WriteHtmlAttribute());
二、添加一个自定义IHttpModule类
添加一个类RouterHttpModule,该类继承自 IHttpModule接口。该类主要功能是对Http请求进行过滤(比如过滤掉资源文件或表单请求),然后根据Url分析出静态页面文件地址,并判断静态页面html文件是否存在,如果存在直接返回静态页面给客户端,否则进入应用程序。
/// <summary>
/// 自定义IHttpModule,分析当前请求的Url信息
/// </summary>
/// <remarks>
/// 作者: Traicne
/// 时间: 2015-10-20
/// </remarks>
public class RouterHttpModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += this.Application_BeginRequest; //注册事件
} private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
string filePath = context.Request.FilePath;
string fileExtension = VirtualPathUtility.GetExtension(filePath);
//如果当前请求的不是资源文件、不是后台管理、请求中没有表单信息、静态页面存在,则返回静态页面
if (string.IsNullOrEmpty(fileExtension) && !filePath.ToLower().StartsWith("/admin") && context.Request.Form.Count.Equals())
{
string htmlPath = context.Request.HtmlFilePath();
if (File.Exists(htmlPath))
{
context.Response.WriteFile(htmlPath);
context.Response.End();
}
}
} public void Dispose() { }
}
然后需要在配置文件Web.config中添加节点,应用程序才会执行刚刚自定义的IHttpModule对象。IIS6和IIS7添加节点的方式也不同
<!--IIS6-->
<system.web>
<httpModules>
<add name="RouterHttpModule" type="GTA.CMS.Site.Web.Common.RouterHttpModule,GTA.CMS.Site.Web"/>
</httpModules>
</system.web> <!--IIS7-->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="RouterHttpModule" type="GTA.CMS.Site.Web.Common.RouterHttpModule,GTA.CMS.Site.Web"/>
</modules>
</system.webServer>
下一篇将会提到后来我在实现过程中将ResultFilter自定义筛选器实现的功能转移到IHttpModule中来实现 Asp.Net MVC页面静态化功能实现一:利用IHttpModule,摒弃ResultFilter
最后这里要注意的是:IHttpModule通过Url分析出来的静态页面文件路径和自定义筛选器通过Url分析出来的静态页面文件路径要一致
Asp.Net MVC页面静态化功能实现一:利用IHttpModule和ResultFilter的更多相关文章
- Asp.Net MVC页面静态化功能实现二:用递归算法来实现
上一篇提到采用IHttpModule来实现当用户访问网站的时候,通过重新定义Response.Filter来实现将返回给客户端的html代码保存,以便用户下一次访问是直接访问静态页面. Asp.Net ...
- Asp.Net MVC页面静态化功能实现一:利用IHttpModule,摒弃ResultFilter
上一篇有提到利用IHttpModule和ResultFilter实现页面静态化功能.后来经过一些改动,将ResultFilter中要实现的功能全部转移到IHttpModule中来实现 Asp.Net ...
- ASP.NET MVC 页面静态化操作的思路
本文主要讲述了在asp.net mvc中,页面静态化的几种思路和方法.对于网站来说,生成纯html静态页面除了有利于seo外,还可以减轻网站的负载能力和提高网站性能.在asp.net mvc中,视图的 ...
- 利用ResultFilter实现asp.net mvc 页面静态化
为了提高网站性能.和网站的负载能力,页面静态化是一种有效的方式,这里对于asp.net mvc3 构架下的网站,提供一种个人认为比较好的静态话方式. 实现原理是通过mvc提供的过滤器扩展点实现页面内容 ...
- Asp.net Mvc 页面静态化
http://www.cnblogs.com/gowhy/archive/2013/01/01/2841472.html
- Asp.net动态页面静态化之初始NVelocity模板引擎
Asp.net动态页面静态化之初始NVelocity模板引擎 静态页面是网页的代码都在页面中,不须要运行asp,php,jsp,.net等程序生成client网页代码的网页,静态页面网址中一般不含&q ...
- MVC页面静态化
MVC 页面静态化 最近工作需要,实现页面静态化,以前在ASP时代,都是FSO自己手动生成的. 新时代,MVC了,当然也要新技术,网上一搜,找到一种解决方案,是基于MVC3的,实现原理是通过mvc ...
- MVC 页面静态化
最近工作需要,实现页面静态化,以前在ASP时代,都是FSO自己手动生成的. 新时代,MVC了,当然也要新技术,网上一搜,找到一种解决方案,是基于MVC3的,实现原理是通过mvc提供的过滤器扩展点实现页 ...
- 利用ResultFilter实现asp.net mvc3 页面静态化
为了提高网站性能.和网站的负载能力,页面静态化是一种有效的方式,这里对于asp.net mvc3 构架下的网站,提供一种个人认为比较好的静态话方式. 实现原理是通过mvc提供的过滤器扩展点实现页面内容 ...
随机推荐
- 关于TCP/IP协议栈(转)
1. TCP/IP协议栈 与OSI参考模型不同,TCP/IP协议栈共有4层,其中网络接口层对应OSI中的物理层和数据链路层,应用层对应OSI中的应用层.表示层和会话层. 在网络接口层的主要协议有:AR ...
- mysql函数二
四.条件推断函数 1.if(expr,v1,v2)函数:成立返回结果v1,否则结果v2 例:select id,if(grade>=60,'pass','fail') from t; 2.IFN ...
- extjs每一个组件要设置唯一的ID
extjs每一个组件要设置唯一的ID,否则会造成各种错误 EXTJS基本上是靠ID来识别组件的,假如你在panel1中有个ID:"keyword"的textfield,而panel ...
- 每天收获一点点------Hadoop RPC机制的使用
一.RPC基础概念 1.1 RPC的基础概念 RPC,即Remote Procdure Call,中文名:远程过程调用: (1)它允许一台计算机程序远程调用另外一台计算机的子程序,而不用去关心底层的网 ...
- malloc,free简单的实现
有关标准库首先简要malloc其原理: 标准库内部通过一个双向链表.管理在堆中动态分配的内存. malloc函数分配内存时会附加若干(一般是12个)字节,存放控制信息. 该信息 ...
- RQNOJ PID4 / 数列(位运算)
题目描述 给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当k=3时,这个序列是: 1,3,4,9,10,12,13,… (该序列实际上就是 ...
- C++ 在dynamic_cast<>用法
/*这是从网上断开的试样.主要是关于 dynamic_cast<> 用法.*/ /* 行动:对象指向一个基类(或参考)cast一个指向派生类,dynamic_cast将基于一个基类指针确实 ...
- POJ 3233 Matrix Power Series(矩阵高速功率+二分法)
职务地址:POJ 3233 题目大意:给定矩阵A,求A + A^2 + A^3 + - + A^k的结果(两个矩阵相加就是相应位置分别相加).输出的数据mod m. k<=10^9. 这 ...
- Mac在结构quick cocos2d-x编译环境
关于 Quick 很多其它的使用说明可參考安装文件夹下的 README 文件. Quick-Coco2d-x开发工具 普通情况下,我们通常都会採用Cocos Code IDE作为开发工具来高速开发游戏 ...
- MAC使用小技巧(一)
[ Mac OS X 终端命令开启功能 ] 1.Lion下显示资源库方法一:显示在“终端”中输入下面的命令:chflags nohidden ~/Library/ 隐藏在“终端”中输入下面的命令:ch ...