ASP.NET MVC中,动态处理页面静态化 【转载】
首先解释一下什么是动态处理页面静态化
对于需要静态化的页面,第一次访问某个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中,动态处理页面静态化 【转载】的更多相关文章
- ASP.NET MVC中,动态处理页面静态化
首先解释一下什么是动态处理页面静态化 对于需要静态化的页面,第一次访问某个Action时,会先执行Action,并在页面渲染后向Response和服务器中网站的目录下都写入需要返回的html,而第二次 ...
- C# MVC 用户登录状态判断 【C#】list 去重(转载) js 日期格式转换(转载) C#日期转换(转载) Nullable<System.DateTime>日期格式转换 (转载) Asp.Net MVC中Action跳转(转载)
C# MVC 用户登录状态判断 来源:https://www.cnblogs.com/cherryzhou/p/4978342.html 在Filters文件夹下添加一个类Authenticati ...
- windows server 证书的颁发与IIS证书的使用 Dapper入门使用,代替你的DbSQLhelper Asp.Net MVC中Action跳转(转载)
windows server 证书的颁发与IIS证书的使用 最近工作业务要是用服务器证书验证,在这里记录下一. 1.添加服务器角色 [证书服务] 2.一路下一步直到证书服务安装完成; 3.选择圈选 ...
- ASP.NET使用HttpHandler进行页面静态化(自动生成页面)
这次的Demo是,一个根页面,点击链接创建子页面,子页面都是一个Template页面进行替换的 一个根页面 <%@ Page Language="C#" AutoEventW ...
- Asp.Net MVC中Action跳转(转载)
首先action的跳转大致归类: 1跳转到与当前同一控制器内的action和不同控制器内的action. 2带有参数的action跳转和不带参数的action跳转. 3跳转到指定视图,不经过Contr ...
- ASP.NET MVC 页面静态化操作的思路
本文主要讲述了在asp.net mvc中,页面静态化的几种思路和方法.对于网站来说,生成纯html静态页面除了有利于seo外,还可以减轻网站的负载能力和提高网站性能.在asp.net mvc中,视图的 ...
- Asp.Net MVC页面静态化功能实现二:用递归算法来实现
上一篇提到采用IHttpModule来实现当用户访问网站的时候,通过重新定义Response.Filter来实现将返回给客户端的html代码保存,以便用户下一次访问是直接访问静态页面. Asp.Net ...
- Asp.Net MVC页面静态化功能实现一:利用IHttpModule,摒弃ResultFilter
上一篇有提到利用IHttpModule和ResultFilter实现页面静态化功能.后来经过一些改动,将ResultFilter中要实现的功能全部转移到IHttpModule中来实现 Asp.Net ...
- Asp.Net MVC页面静态化功能实现一:利用IHttpModule和ResultFilter
由于公司现在所采用的是一套CMS内容管理系统的框架,所以最近项目中有一个需求提到要求实现页面静态化的功能.在网上查询了一些资料和文献,最后采用的是小尾鱼的池塘提供的 利用ResultFilter实现a ...
随机推荐
- java 的序列化与反序列化
前言: 一直很不理解java的序列化的概念,为什么java对象的序列化要实现 Serializable的接口?或者要实现Externalizable的接口?而且Externalizable 的父类还是 ...
- 消息队列kafka集群搭建
linux系统kafka集群搭建(3个节点192.168.204.128.192.168.204.129.192.168.204.130) 本篇文章kafka集群采用外部zookeeper,没采 ...
- nc/netcat命令
nc/netcat命令 语法 nc/netcat(选项)(参数) 选项 -g<网关>:设置路由器跃程通信网关,最多设置8个: -G<指向器数目>:设置来源路由指向器,其数值为4 ...
- Vue的计算属性,监视属性代码理解
1.计算属性:在computed属性对象中定义计算属性的方法,在页面中使用{{方法名}}来显示计算的结果 //计算属性 computed:{ // 计算属性值的一个方法,方法的返回值是属性值,初始化显 ...
- filter以及reduce的用法
简单的写了就几个例子 # 删掉偶数 li = [1,2,3,4,5,6,7,8,9,10] print(list(filter( lambda x : not x % 2 ==0 ,li))) #保留 ...
- grafana 安装配置
Grafana安装配置 1.下载安装包 wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.1.3.l ...
- 关于shell命令的一些用法和技巧
#!/bin/bash #第一种写法 #date=`date "+%Y-%m-%d %H:%M:%S"` #第二种写法 date=$(date "+%Y-%m-%d %H ...
- QT自定义控件系列(二) --- Loading加载动画控件
本系列主要使用Qt painter来实现一些基础控件.主要是对平时自行编写的一些自定义控件的总结. 为了简洁.低耦合,我们尽量不使用图片,qrc,ui等文件,而只使用c++的.h和.cpp文件. 由于 ...
- 路径R
定义文件路径时前面加个r 例如 firstfolder = r"C:\Users\1261\Desktop\" 不对其中的符号进行转义
- iOS 10 Programming Fundamentals with Swift 学习笔记 0
1,a single statement can be broken into multiple lines ,For example, after an opening parenthesis is ...