首先解释一下什么是动态处理页面静态化

  对于需要静态化的页面,第一次访问某个Action时,会先执行Action,并在页面渲染后向Response和服务器中网站的目录下都写入需要返回的html,而第二次访问此页时,在执行Action前,程序会先在指定目录下寻找是否存在当前请求对应的静态页面,如果有,则直接返回静态页面,如果没有,则按第一次访问此请求进行处理,即执行Action,并向Response和服务器中网站的目录下都写入需要返回的html。利用这种方式,可以在网站在请求的过程中,会动态的生成静态页面,而无需人工干预,方便快捷。

接下来直接上代码

    /// <summary>
/// 页面静态化过滤器
/// 思路:在执行Action前,先判断此Action返回的View()的静态文件是否存在
/// 如果存在,则直接返回静态文件。
/// 如果不存在,则利用OnResultExecuting,替换Response中的输出流,让渲染后的html写入到
/// 本过滤器定义的StringBuilder中,然后在OnResultExecuted中(页面渲染后),从StringBuilder
/// 中获取html,并同时写入到静态文件和Response的内置输出流中
///
/// 注:由于我没找到直接从Response中获取输出流的html的方法,因此我这里是替换了Response中的output属性,
/// 替换后,渲染后的结果就会输出到我们自己写的StringBuilder中(此时Response中并没有html),此时在渲染后,
/// 再把StringBuilder中的html,分别写入静态文件和Response中(tw.write方法),完成此次请求。
/// </summary>
public class StaticHtmlFilter : ActionFilterAttribute
{
//用于保存渲染后的html文本
static StringBuilder sb;
//这几个Writer照着写就行了
static StringWriter sw;
static HtmlTextWriter hw;
static TextWriter tw;
//自定义的静态页面的后缀名
static string ext = ".html";
//静态页面的绝对路径(包括后缀名)
string fileName = null;
///静态页面的绝对路径(不包括后缀名)
static string path = null;
//静态文件是否存在
bool FileExists = false; /// <summary>
/// Action执行前,判断当前页面是否已经被静态化(Views路径下是否存在html文件)
/// 如果存在静态文件则直接设置filterContext的result,即返回html作为结果,而不执行Action中代码
/// 如果不存在静态页面文件,则不设置filterContext的result,此时将会执行Action中的代码
/// </summary>
/// <param name="filterContext"></param>
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//根据controller和action信息
string controller = filterContext.RouteData.Values["controller"].ToString();
string action = filterContext.RouteData.Values["action"].ToString();
object id=null;
//路由中是否包含可选参数id,如果有,则在文件名也要体现
if (!filterContext.RouteData.Values.TryGetValue("id", out id))
{
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Views", controller, action);
fileName = string.Format("{0}{1}", path, ext);
}
else
{
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Views", controller, action);
fileName = string.Format("{0}{1}{2}", path, id.ToString(),ext);
}
//拼装后缀名 FileExists = File.Exists(fileName);
//如果文件存在,直接返回结果
if (FileExists)
{
filterContext.Result = new FileContentResult(File.ReadAllBytes(fileName), "text/html; charset=utf-8");
}
}
/// <summary>
/// 执行完Action后,但渲染页面前执行此处
/// 渲染页面的意思是将cshtml中的后台代码,翻译为前台代码
///
/// </summary>
/// <param name="filterContext"></param>
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
       
if (!FileExists)
{
//保存html
sb = new StringBuilder();
//两个writer
sw = new StringWriter(sb);
hw = new HtmlTextWriter(sw);
//记住Response中原本输出流,用于返回本次请求的html,与下一句配合使用
//在渲染结束后,向tw内写入html内容
tw = filterContext.RequestContext.HttpContext.Response.Output;
//过滤器自己输出流,用于获取渲染后的html内容
filterContext.RequestContext.HttpContext.Response.Output = hw;
} }
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
//如果是静态文件不存在
if (!FileExists)
{
//获取渲染后的html文本
string res = sb.ToString();
//将文本写入到静态文件中
new Action(() => File.WriteAllText(fileName, res)).BeginInvoke(null, null);
//向Response的输出流中写入本次请求的html
tw.Write(sb.ToString());
}
}
}

什么样的Action适合静态化?

我认为有两种Action需要使用静态化

1.登录页面等无需向Action中传入参数而直接返回View的Action需要静态处理。

 /// <summary>
/// 登录
/// </summary>
/// <returns></returns>
[AllowAnonymous]
[StaticHtmlFilter]
public ActionResult Login()
{ var model = new LoginDto
{
ReturnUrl = Request.QueryString["ReturnUrl"],
LoginName = "admin",
Password = "qwaszx"
};
if (User.Identity.IsAuthenticated)
{
if (model.ReturnUrl.IsNotBlank())
return Redirect(model.ReturnUrl);
return RedirectToAction("Index");
}
return View(model);
}

2.通过一个参数进行查询的Action(注意是查询,非编辑)

        /// <summary>
/// 编辑
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[StaticHtmlFilter]
public async Task<ActionResult> Edit(string id)
{
var model = await _menuService.Find(id);
return View(model);
}

注意事项

  对于经常需要编辑的内容的查询页面,如商品列表如使用动态处理静态化页面,则应在编辑商品信息后,删除服务器指定目录下的静态页面,以便于页面更新。

  当然我们也可以在上面的过滤器中的 OnActionExecuting 方法在判断文件是否存在时,先判断本次请求是否是编辑操作,如果是则删除相应的静态文件重新生成即可。

注:有些地方我想得还不够充分,希望大家多提意见。

                                                              

ASP.NET MVC中,动态处理页面静态化的更多相关文章

  1. ASP.NET MVC中,动态处理页面静态化 【转载】

    首先解释一下什么是动态处理页面静态化 对于需要静态化的页面,第一次访问某个Action时,会先执行Action,并在页面渲染后向Response和服务器中网站的目录下都写入需要返回的html,而第二次 ...

  2. ASP.NET使用HttpHandler进行页面静态化(自动生成页面)

    这次的Demo是,一个根页面,点击链接创建子页面,子页面都是一个Template页面进行替换的 一个根页面 <%@ Page Language="C#" AutoEventW ...

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

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

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

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

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

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

  6. Asp.Net MVC页面静态化功能实现一:利用IHttpModule和ResultFilter

    由于公司现在所采用的是一套CMS内容管理系统的框架,所以最近项目中有一个需求提到要求实现页面静态化的功能.在网上查询了一些资料和文献,最后采用的是小尾鱼的池塘提供的 利用ResultFilter实现a ...

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

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

  8. ASP.NET MVC使用SSI来实现页面静态化

    页面静态化分为两种:伪静态和真静态,这里主要介绍的是真静态. 进入正题之前先简单介绍一下SSI和shtml: 1).SSI是Server Side Include的简称(服务器端嵌入) 2).shtm ...

  9. Spring MVC 学习总结(七)——FreeMarker模板引擎与动态页面静态化

    模板引擎可以让程序实现界面与数据分离,业务代码与逻辑代码的分离,这就提升了开发效率,良好的设计也使得代码复用变得更加容易.一般的模板引擎都包含一个模板解析器和一套标记语言,好的模板引擎有简洁的语法规则 ...

随机推荐

  1. put与putIfAbsent区别

    put与putIfAbsent区别: put在放入数据时,如果放入数据的key已经存在与Map中,最后放入的数据会覆盖之前存在的数据, 而putIfAbsent在放入数据时,如果存在重复的key,那么 ...

  2. JS 基本类型和引用类型---JS 学习笔记(一)

    本文参考了focusxxxxy的博客,感谢他的知识分享. 一 基本类型和引用类型的值 ECMAScript 变量包含两种不同数据类型的值:基本类型和引用类型. 也有其他的叫法,比如原始类型和对象类型, ...

  3. winform使用log4.net

    因为我最近负责的Winform项目,好多都用到了这个log4net的日志功能,开发程序对数据一般都要求做到雁过留痕,所以日志对于我们程序员是不可或缺.因此我把对log4net的使用做一个记录总结,以便 ...

  4. Kafka集群安装部署、Kafka生产者、Kafka消费者

    Storm上游数据源之Kakfa 目标: 理解Storm消费的数据来源.理解JMS规范.理解Kafka核心组件.掌握Kakfa生产者API.掌握Kafka消费者API.对流式计算的生态环境有深入的了解 ...

  5. Asp.net core Identity + identity server + angular 学习笔记 (第三篇)

    register -> login 讲了 我们来讲讲 forgot password -> reset password  和 change password 吧 先来 forgot pa ...

  6. VBA正则笔记 理解肯定环视

    之前没有理解好,还以为是学习笔记有谬误. 'VBA正则笔记 肯定环视 Public Sub RegExHandle() Dim Regex As Object Dim Mh As Object, On ...

  7. session和cookie的简介

    Session(时域)在计算机中,尤其是在网络应用中,称为“会话控制”.Session 对象存储特定用户会话所需的属性及配置信息.这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session ...

  8. LDA(线性判别分类器)学习笔记

    Linear Discriminant Analysis(线性判别分类器)是对费舍尔的线性鉴别方法(FLD)的归纳,属于监督学习的方法. LDA的基本思想是将高维的模式样本投影到最佳鉴别矢量空间,以达 ...

  9. XV Open Cup named after E.V. Pankratiev. GP of Siberia-Swimming

    给出两个点,找到过这两个点的等角螺线,并求出中间的螺线长 $c = \frac{b}{a}$ $p = a \times c^{\frac{\theta}{angle}}$ 对弧线积分 #includ ...

  10. PAT 1144 The Missing Number

    1144 The Missing Number (20 分)   Given N integers, you are supposed to find the smallest positive in ...