本文标题是指对已经生成了HTML的页面做一些输出到客户端之前的处理。

方法的原理是:把Response的输出重定向到自定义的容器内,也就是我们的StringBuilder对象里,在HTML所有的向页面输出都变成了向StringBuilder输出,然后我们对StringBuilder处理完成之后,再把Response的输出重定向到原来的页面上,然后再通过Response.Write方法把StringBuilder的内容输出到页面上

这里之所以用反射,是因为Response对象的OutPut属性是只读的,通过反编译该类的程序集发现,OutPut实际上是内部私有成员 _writer来实现输出的。因此通过反射来改写该成员的值以实现输出流的重定向。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.UI;
  6. using System.Web.UI.WebControls;
  7. using System.Text;
  8. using System.IO;
  9. using System.Reflection;
  10. public partial class _Default : System.Web.UI.Page
  11. {
  12. StringBuilder content = new StringBuilder();
  13. TextWriter tw_old, tw_new;
  14. FieldInfo tw_field;
  15. protected void Page_Load(object sender, EventArgs e)
  16. {
  17. var context = HttpContext.Current;
  18. tw_old = context.Response.Output;//Response原来的OutPut
  19. tw_new = new StringWriter(content);//一个StringWriter,用来获取页面内容
  20. var type_rp = context.Response.GetType();
  21. //通过反射获取对象的私有字段
  22. tw_field = type_rp.GetField("_writer", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  23. tw_field.SetValue(context.Response, tw_new);
  24. }
  25. protected override void Render(HtmlTextWriter writer)
  26. {
  27. base.Render(writer);
  28. //替换回Response的OutPut
  29. tw_field.SetValue(HttpContext.Current.Response, tw_old);
  30. //做自己的处理
  31. content.AppendLine("<!--江湖小子-->");
  32. HttpContext.Current.Response.Write(content.ToString());
  33. }
  34. }
  35. 方法二,用HttpModul来实现:
  36. using System;
  37. using System.Collections.Generic;
  38. using System.Linq;
  39. using System.Web;
  40. using System.Web.UI;
  41. using System.IO;
  42. using System.Text;
  43. using System.Reflection;
  44. /// <summary>
  45. ///HttpModule 的摘要说明
  46. /// </summary>
  47. public class HttpModule : IHttpModule
  48. {
  49. private HttpApplication _contextApplication;
  50. private TextWriter tw_new, tw_old;
  51. private StringBuilder _content;
  52. private FieldInfo tw_field;
  53. public void Init(HttpApplication context)
  54. {
  55. _contextApplication = context;
  56. _contextApplication.PreRequestHandlerExecute += new EventHandler(_contextApplication_PreRequestHandlerExecute);
  57. }
  58. public void Dispose()
  59. {
  60. _contextApplication = null;
  61. _contextApplication.Dispose();
  62. }
  63. public void _contextApplication_PreRequestHandlerExecute(object sender, EventArgs e)
  64. {
  65. HttpContext context = _contextApplication.Context;
  66. var _page = context.Handler as System.Web.UI.Page;
  67. _page.Unload += new EventHandler(_page_Unload);
  68. _content = new StringBuilder();
  69. tw_old = context.Response.Output;//Response原来的OutPut
  70. tw_new = new StringWriter(_content);//一个StringWriter,用来获取页面内容
  71. var type_rp = context.Response.GetType();
  72. tw_field = type_rp.GetField("_writer", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  73. tw_field.SetValue(context.Response, tw_new);
  74. }
  75. void _page_Unload(object sender, EventArgs e)
  76. {
  77. //替换回Response的OutPut
  78. tw_field.SetValue(HttpContext.Current.Response, tw_old);
  79. //做自己的处理
  80. _content.AppendLine("<!--江湖小子-->");
  81. HttpContext.Current.Response.Write(_content.ToString());
  82. }
  83. }
  84. 方法三:
  85. public class HttpModule : IHttpModule
  86. {
  87. private HttpApplication _contextApplication;
  88. private TextWriter tw_new, tw_old;
  89. private StringBuilder _content;
  90. private FieldInfo tw_field;
  91. public void Init(HttpApplication application)
  92. {
  93. _contextApplication = application;
  94. _contextApplication.BeginRequest += new EventHandler(_contextApplication_BeginRequest);
  95. _contextApplication.EndRequest +=new EventHandler(_contextApplication_EndRequest);
  96. }
  97. void _contextApplication_BeginRequest(object sender, EventArgs e)
  98. {
  99. _content = new StringBuilder();
  100. tw_old = _contextApplication.Response.Output;
  101. tw_new = new StringWriter(_content);
  102. var type_rp = _contextApplication.Response.GetType();
  103. tw_field = type_rp.GetField("_writer", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  104. tw_field.SetValue(_contextApplication.Response, tw_new);
  105. }
  106. void _contextApplication_EndRequest(object sender, EventArgs e)
  107. {
  108. tw_field.SetValue(_contextApplication.Response, tw_old);
  109. //做自己的处理
  110. _content.AppendLine("<!--jhxz-->");
  111. _contextApplication.Response.Write(_content.ToString());
  112. }
  113. public void Dispose()
  114. {
  115. _contextApplication = null;
  116. _contextApplication.Dispose();
  117. }
  118. }

最后还是推荐一篇好文:码农欧洲出差的一点小插曲

拦截asp.net输出流做处理的更多相关文章

  1. 拦截asp.net输出流做处理, 拦截HTML文本(asp.net webForm版)

    对已经生成了HTML的页面做一些输出到客户端之前的处理 方法的原理是:把Response的输出重定向到自定义的容器内,也就是我们的StringBuilder对象里,在HTML所有的向页面输出都变 成了 ...

  2. 拦截asp.net输出流并进行处理的方法

    本文实例主要实现对已经生成了HTML的页面做一些输出到客户端之前的处理. 方法的实现原理是:把Response的输出重定向到自定义的容器内,也就是我们的StringBuilder对象里,在HTML所有 ...

  3. 拦截asp.net mvc输出流做处理, 拦截HTML文本(asp.net MVC版)

    以前的一个贴子写过一个webForm的拦截HTML输出流的版本,最近用到mvc时用同样的方式发生一些问题. 如下图 查了好久也不知道啥原因. 好吧, 我最后选择放弃. 想起以前自定义Response. ...

  4. ASP.NET CORE做的网站运行在docker实践

    用VS2017 建立了 DotNet Core 2.2 的网站后,如何转移到 Docker 下运行? 下面分两种方式来实践: 1.直接手动命今行,将本机目录映射进Docker,运行网站.2.制作 Im ...

  5. ASP.NET MVC 做的网站项目

    感谢博客园团队日夜为广大需要获取知识人们所做的奉献 博客园团队您们辛苦了 ASP.NET MVC 实现有论坛功能的网站(有iis发布网站 这是之前写的... www.lazyfitness.cn 经过 ...

  6. 牛腩学ASP.NET CORE做博客(视频)

    牛腩学习ASP.NET CORE做的项目,边学边做. 目录: 01-dotnetcore网站部署到centos7系统上(时长 2:03:16) 02-前期准备及项目搭建 (时长:0:23:35) 03 ...

  7. win10 uwp 使用 asp dotnet core 做图床服务器客户端

    原文 win10 uwp 使用 asp dotnet core 做图床服务器客户端 本文告诉大家如何在 UWP 做客户端和 asp dotnet core 做服务器端来做一个图床工具   服务器端 从 ...

  8. win10 uwp 手把手教你使用 asp dotnet core 做 cs 程序

    本文是一个非常简单的博客,让大家知道如何使用 asp dot net core 做后台,使用 UWP 或 WPF 等做前台. 本文因为没有什么业务,也不想做管理系统,所以看到起来是很简单. Visua ...

  9. ASP.NET输出流至少要有256个字节的数据后Response.Flush方法才会生效

    很多时候我们写的asp.net程序会因为做很多操作,所以会花上一分钟甚至几分钟时间.为了使软件使用者能够耐心的等待程序的执行,我们经常会希望有一个进度条来表示程序执行的状态.或者最起码要显示一个类似: ...

随机推荐

  1. 第四周作业——C语言自评

    1.你对自己的未来有什么规划?做了哪些准备?以目前的现状来说,希望至少能够掌握专业所要求的基本操作,然后一步步去深入.提升,毕业之后不会灰溜溜的一次次求职失败.目前更多的是利用闲暇时间补回过去老师同学 ...

  2. lintcode-201-线段树的构造

    201-线段树的构造 线段树是一棵二叉树,他的每个节点包含了两个额外的属性start和end用于表示该节点所代表的区间.start和end都是整数,并按照如下的方式赋值: 根节点的 start 和 e ...

  3. C++ Primer Plus学习:第四章

    C++入门第四章:复合类型 1 数组 数组(array)是一种数据格式,能够存储多个同类型的值. 使用数组前,首先要声明.声明包括三个方面: 存储每个元素中值的类型 数组名 数组中的元素个数 声明的通 ...

  4. C语言语法树

  5. 2nd 燃尽图

    燃尽图(burn down chart) 在项目完成之前,对需要完成的工作所作的一种可视化表示.燃尽图主要用于向项目组成员和用户提供一个工作进展的公共视图,用以描述项目的实现状态.一般来说,常常用于形 ...

  6. TeamCity编译执行selenium上传窗口脚本缺陷

    2015-07-04 18:05 编写本文 TeamCity编译selenium脚本,对于上传窗口处理只支持sendKeys的使用,不支持模拟人为按下Enter键和使用autoIt等操作,即使本地调试 ...

  7. selenium webdriver XPath的定位方法练习 !

    html  代码: <html> <body> <div id="div1"> <input name="divl1input& ...

  8. elasticsearch6 学习之基础CURD

    环境:elasticsearch6.1.2        kibana6.1.2  基础概念: 1._index元数据 (1)代表一个document存放在哪个index中(2)类似的数据放在一个索引 ...

  9. 数据库引擎InnoDB和MyISAM区别

    MyISAM是MySQL的默认数据库引擎(5.5版之前),由早期的ISAM(Indexed Sequential Access Method:有索引的顺序访问方法)所改良.虽然性能极佳,但却有一个缺点 ...

  10. 【Jmeter】集合点Synchronizing Timer

    集合点: 简单来理解一下,虽然我们的“性能测试”理解为“多用户并发测试”,但真正的并发是不存在的,为了更真实的实现并发这感念,我们可以在需要压力的地方设置集合点,每到输入用户名和密码登录时,所有的虚拟 ...