由于公司现在所采用的是一套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的更多相关文章

  1. Asp.Net MVC页面静态化功能实现二:用递归算法来实现

    上一篇提到采用IHttpModule来实现当用户访问网站的时候,通过重新定义Response.Filter来实现将返回给客户端的html代码保存,以便用户下一次访问是直接访问静态页面. Asp.Net ...

  2. Asp.Net MVC页面静态化功能实现一:利用IHttpModule,摒弃ResultFilter

    上一篇有提到利用IHttpModule和ResultFilter实现页面静态化功能.后来经过一些改动,将ResultFilter中要实现的功能全部转移到IHttpModule中来实现 Asp.Net ...

  3. ASP.NET MVC 页面静态化操作的思路

    本文主要讲述了在asp.net mvc中,页面静态化的几种思路和方法.对于网站来说,生成纯html静态页面除了有利于seo外,还可以减轻网站的负载能力和提高网站性能.在asp.net mvc中,视图的 ...

  4. 利用ResultFilter实现asp.net mvc 页面静态化

    为了提高网站性能.和网站的负载能力,页面静态化是一种有效的方式,这里对于asp.net mvc3 构架下的网站,提供一种个人认为比较好的静态话方式. 实现原理是通过mvc提供的过滤器扩展点实现页面内容 ...

  5. Asp.net Mvc 页面静态化

    http://www.cnblogs.com/gowhy/archive/2013/01/01/2841472.html

  6. Asp.net动态页面静态化之初始NVelocity模板引擎

    Asp.net动态页面静态化之初始NVelocity模板引擎 静态页面是网页的代码都在页面中,不须要运行asp,php,jsp,.net等程序生成client网页代码的网页,静态页面网址中一般不含&q ...

  7. MVC页面静态化

    MVC 页面静态化   最近工作需要,实现页面静态化,以前在ASP时代,都是FSO自己手动生成的. 新时代,MVC了,当然也要新技术,网上一搜,找到一种解决方案,是基于MVC3的,实现原理是通过mvc ...

  8. MVC 页面静态化

    最近工作需要,实现页面静态化,以前在ASP时代,都是FSO自己手动生成的. 新时代,MVC了,当然也要新技术,网上一搜,找到一种解决方案,是基于MVC3的,实现原理是通过mvc提供的过滤器扩展点实现页 ...

  9. 利用ResultFilter实现asp.net mvc3 页面静态化

    为了提高网站性能.和网站的负载能力,页面静态化是一种有效的方式,这里对于asp.net mvc3 构架下的网站,提供一种个人认为比较好的静态话方式. 实现原理是通过mvc提供的过滤器扩展点实现页面内容 ...

随机推荐

  1. hdu1796 How many integers can you find

    //设置m,Q小于n可以设置如何几号m随机多项整除 //利用已知的容斥原理 //ans = 数是由数的数目整除 - 数为整除的两个数的数的最小公倍数 + 由三个数字... #include<cs ...

  2. SharePoint管理中心来配置资源限制(大名单)

    SharePoint管理中心来配置资源限制(大名单) 名单SharePoint核心.SharePoint一切的一切都是列表. 我可以说SharePoint内容为驱动的列表. 之前版本号的SharePo ...

  3. Git Config(转)

    一.Git已经在你的系统中了,你会做一些事情来客户化你的Git环境.   你只需要做这些设置一次:即使你升级了,他们也会绑定到你的环境中.你也可以在任何时刻通过运行命令来重新更改这些设置.      ...

  4. 具体分析Struts工作流程

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXV3ZW56aGU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...

  5. linux Apache rotatelogs 故障原因及解决方案未生效

    rotatelogs 截断日志.构造.但保存vhost.conf 之后.serverhttpd -k restart 还是无法成功重新启动. 日志文件: (2)No such file or dire ...

  6. PHP MVC自己主动RBAC自己主动生成的访问路由

    使用的关键点: ReflectionClass class Rbac extends MY_Controller { public function index() { $arr = glob( __ ...

  7. IOS遍历未知对象属性、函数

    #import <objc/runtime.h> @implementation NSObject (PropertyListing) /* 获取对象的全部属性 */ - (NSDicti ...

  8. jQuery自定义右键菜单

    首先看下效果,效果在最下面: 代码: body { font-size: 12px; margin: 0px; padding: 0px; } form,div,ul,li { margin: 0px ...

  9. HDU 4107 线段树

    给出N个节点,M次操作,和p 每次操作 对l-r区间的每一个节点+c,若节点值>=p,则加2*c: 结点存当前区间伤害最小值,最大值,以及lazy操作.更新到假设最小值大于等于P,或者最大值小于 ...

  10. 【百度地图API】如何制作泡泡放大镜?

    原文:[百度地图API]如何制作泡泡放大镜? 任务描述: 我不喜欢API提供的缩放控件耶…… 我能不能使用其他方式放大地图勒? 当然阔以啦! 现在就来教大家如何动手制作一个可爱的泡泡放大镜! 使用它, ...