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

  对于需要静态化的页面,第一次访问某个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. 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 ...

  3. windows server 证书的颁发与IIS证书的使用 Dapper入门使用,代替你的DbSQLhelper Asp.Net MVC中Action跳转(转载)

    windows server 证书的颁发与IIS证书的使用   最近工作业务要是用服务器证书验证,在这里记录下一. 1.添加服务器角色 [证书服务] 2.一路下一步直到证书服务安装完成; 3.选择圈选 ...

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

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

  5. Asp.Net MVC中Action跳转(转载)

    首先action的跳转大致归类: 1跳转到与当前同一控制器内的action和不同控制器内的action. 2带有参数的action跳转和不带参数的action跳转. 3跳转到指定视图,不经过Contr ...

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

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

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

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

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

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

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

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

随机推荐

  1. 将float数据类型转换为str

    示例程序: #include <stdio.h> . . void UART_send_byte(char dat); void UART_send_string(unsigned cha ...

  2. GridControl 主从模式(Master-detail)子表格获取行数据

    今天遇到一个问题,gridcontrol使用主从表的时候,在子表中获取子表的行数据时居然获取不到,郁闷了很久.然后在网上找到方法(出处在这里:https://q.cnblogs.com/q/83412 ...

  3. Problem 3: Largest prime factor

    The prime factors of 13195 are 5, 7, 13 and 29. What is the largest prime factor of the number 60085 ...

  4. Codeforces Round #538 (Div. 2) C. Trailing Loves (or L'oeufs?) (分解质因数)

    题目:http://codeforces.com/problemset/problem/1114/C 题意:给你n,m,让你求n!换算成m进制的末尾0的个数是多少(1<n<1e18    ...

  5. css 清楚浮动的几种方式

    方法一: 使用clear属性的空元素 <div style="clear:both;"></div> 方法二:使用overflow属性 给浮动的元素容器添加 ...

  6. 关于jQuery实现CheckBox全选只能生效一次的问题

    //这代码只有一次全选.全不选的效果 第三次点击checkall会没有任何效果 $("#checkall").click(function(){ $('input[name=&qu ...

  7. 三,用户交互方式与python基本数据类型

    一.与用户交互 input python2中:用户输入什么类型的数据,就储存为什么类型的数据.比如输入数字则储存为整型,输入符号则存储为字符串型.raw_input会将所有输入的类型转换为字符串型. ...

  8. Csrf_token ||| CSRF跨站请求伪造

    # 注: 部分内容参考网上,侵删   CSRF(Cross-site request forgery) 跨站请求伪造,是一种对网站的恶意利用  它会通过伪装成受信任用户的请求来利用受信任的网站来获取一 ...

  9. python爬虫套件在mac上的安装-bs的安装

    1,首先安装pip gem install pip 这种方式会报错: ERROR:  While executing gem ... (Gem::FilePermissionError) You do ...

  10. 团队合作one

    一.项目介绍 为生活在长大的学生提供方快捷的生活服务,通过帖子发现自己志同道合的朋友,记录自己在长大点滴.本项目的意义在于锻炼团队的scrum能力,加强团队合作能力.确定本项目采用的技术方向:本项目整 ...