Asp.net2.0 中自定义过滤器对Response内容进行处理
因项目需要,对每一个访问网站的请求要做原始数据记录,其中要包括几个要素:
1.客户端的IP
2.客户端请求的页面路径
3.客户端发出的请求头
4.服务器返回的正文内容。
在代码设计前分析了一下,前三个都很好解决,对于截获服务器返回的正文,准备用HttpResponse 对象中的Output 和 OutputStream 属性输出信息来解决。
可是在正式编码的过程中,发现Output和OutputStream 并不是想像中可以直接把数据转出取回,耗费了近两天的时间,想尽了一切办法可还是仅仅可以追加内容并无法读取。
在网上查阅到,对于HttpResponse 对象,仅仅可以使用过滤器来对其中将要输出的内容进行修改。
这个过滤器要继承自Stream 类,并要实现其中的虚方法。看来之前企图使用HttpWriter,TextWriter,Stream,HttpStream 这些类来转出数据完全是错误的。
现在有信心来截获服务器返回内容了,说干就干吧!
1.首先要建立一个简易过滤器。
代码如下:
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Web;
/**//// <summary>
/// 定义原始数据EventArgs,便于在截获完整数据后,由事件传递数据
/// </summary>
public class RawDataEventArgs : EventArgs
{
private string sourceCode;
public RawDataEventArgs(string SourceCode)
{
sourceCode = SourceCode;
}
public string SourceCode
{
get { return sourceCode; }
set { sourceCode = value; }
}
}
//自定义过滤器
public class RawFilter : Stream
{
Stream responseStream;
long position;
StringBuilder responseHtml;
/**//// <summary>
/// 当原始数据采集成功后激发。
/// </summary>
public event EventHandler<RawDataEventArgs> OnRawDataRecordedEvent;
public RawFilter(Stream inputStream)
{
responseStream = inputStream;
responseHtml = new StringBuilder();
}
//实现Stream 虚方法
Filter Overrides#region Filter Overrides
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return true;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public override void Close()
{
responseStream.Close();
}
public override void Flush()
{
responseStream.Flush();
}
public override long Length
{
get
{
return 0;
}
}
public override long Position
{
get
{
return position;
}
set
{
position = value;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
return responseStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return responseStream.Seek(offset, origin);
}
public override void SetLength(long length)
{
responseStream.SetLength(length);
}
#endregion
//关键的点,在HttpResponse 输入内容的时候,一定会调用此方法输入数据,所以要在此方法内截获数据
public override void Write(byte[] buffer, int offset, int count)
{
string strBuffer = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);
//采用正则,检查输入的是否有页面结束符</html>
Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);
if (!eof.IsMatch(strBuffer))
{
//页面没有输出完毕,继续追加内容
responseHtml.Append(strBuffer);
}
else
{
//页面输出已经完毕,截获内容
responseHtml.Append(strBuffer);
string finalHtml = responseHtml.ToString();
//激发数据已经获取事件
OnRawDataRecordedEvent(this, new RawDataEventArgs(finalHtml));
//继续传递要发出的内容写入流
byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(finalHtml);
responseStream.Write(data, 0, data.Length);
}
}
}
至此,过滤器定义完毕了,接下来还需要把这个过滤器装配到HttpResponse 对象中。
为了能够截获整站的aspx 页面输出的内容,我们可以定义一个HttpModule 来完成。
代码如下:
using System.Web;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
public class HttpRawDataModule : IHttpModule
{
IHttpModule 成员#region IHttpModule 成员
public void Dispose()
{
}
public void Init(HttpApplication context)
{
//绑定事件,在对此请求处理过程全部结束后进行过滤操作
context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
}
#endregion
/**//// <summary>
/// 对此HTTP请求处理的过程全部结束
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void context_ReleaseRequestState(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
//这里需要针对ASPX页面进行拦截,测试发现如果不这么做,Wap 访问站点图片容易显示为X,奇怪
string[] temp = application.Request.CurrentExecutionFilePath.Split('.');
if (temp.Length > 0 && temp[temp.Length - 1].ToLower() == "aspx")
{
//装配过滤器
application.Response.Filter = new RawFilter(application.Response.Filter);
//绑定过滤器事件
RawFilter filter = (RawFilter)application.Response.Filter;
filter.OnRawDataRecordedEvent += new EventHandler<RawDataEventArgs>(filter_OnRawDataRecordedEvent);
}
}
/**//// <summary>
/// 当原始数据采集到以后,入库
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void filter_OnRawDataRecordedEvent(object sender, RawDataEventArgs e)
{
string allcode = e.SourceCode;
WapSite.SiteDataClass wapdata = new WapSite.SiteDataClass();
wapdata.WriteRawDataLog(allcode);
}
}
HttpModule 准备完毕,也装配上了过滤器,接下来还需要在配置文件中配置HttpModules配置节 ,把自定义的HttpModule 加入到HTTP处理管道中。
在Web.config 中增加配置节如下:
<httpModules>
<add name="RawDataModule" type="HttpRawDataModule"/>
</httpModules>
</system.web>
测试成功,能准确的获得服务器向客户端输出的HTML内容。
其中,在过滤器中,可以直接对即将要输出的内容做 对于字符串的任意处理。
而且采用这样的方式来对站点即将输出的内容做修改和采集,可以通过修改配置文件,随时打开和关闭,有很强的优越性和灵活性还有重用性。
记得看到过很多需要产生静态页面的网站,都是通过代码HttpWebRequest 向自己请求并记录返回的代码产生静态页面,不知道我当前介绍的方法是否更好写,比如需要产生静态页面时,不管是谁发出请求,由服务器检查自己是否有静态页面,否则产生静态页面,并转向。给出引子,希望大家还是自己开阔思路比较好。
Asp.net2.0 中自定义过滤器对Response内容进行处理相关推荐
- .net中自定义过滤器对Response内容进行处理
原文:http://www.cnblogs.com/zgqys1980/archive/2008/09/02/1281895.html 代码DEMO:http://files.cnblogs.com/ ...
- 深度解析ASP.NET2.0中的Callback机制
callback的一般使用方法还算简单,直接参照msdn的帮助和范例就足够了.但是想要真正用好.用精,或者想开发一些基于callback机制的WEB组件,那么,就要先深入了解callback的实现机制 ...
- 在ASP.Net2.0中使用UrlRewritingNet实现链接重写(转)
在ASP.Net2.0中使用UrlRewritingNet实现链接重写 很多时候我们需要链接转向(Url Rewriting),例如二级域名转向.文章访问链接等场合. 让我们看两个例子: 1 你现在看 ...
- ASP.NET2.0中的ClientScriptManager 类用法—如何添加客户端事件!
在ASP.NET2.0中,ClientScriptManager 类通过键 String 和 Type 唯一地标识脚本.具有相同的键和类型的脚本被视为重复脚本.因此,我们可以使用脚本类型来避免混淆可能 ...
- ASP.NET2.0中的全球化与本地化UICulture,Culture
ASP.NET2.0中的全球化与本地化UICulture,Culture 来源:转载 日期:2007-2-28 14:59:01 阅读:324 评论:0 一.简介 全球化和本地化是每一位开发者在创 ...
- 在ASP.Net2.0中使用UrlRewritingNet实现链接重写
在ASP.Net2.0中使用UrlRewritingNet实现链接重写 很多时候我们需要链接转向(Url Rewriting),例如二级域名转向.文章访问链接等场合. 让我们看两个例子: 1 你现在看 ...
- ASP.NET2.0中的ClientScriptManager 类用法—如何添加客户端事件
在ASP.NET2.0中,ClientScriptManager 类通过键 String 和 Type 唯一地标识脚本.具有相同的键和类型的脚本被视为重复脚本.因此,我们可以使用脚本类型来避免混淆可能 ...
- ASP.NET2.0中themes、Skins轻松实现网站换肤!
ASP.NET2.0中themes.Skins轻松实现网站换肤! 可能有些朋友还不是很清楚themes.skins.下面先介绍下themes.skins.. 一.简介: 一看Themes.Skins这 ...
- [导入]ASP.NET2.0中Tabs的简单实现
摘要: ASP.NET2.0中Tabs的简单实现 阅读全文 [新闻]"Wintel"联盟已名存实亡 文章来源:http://www.cnblogs.com/gyche/archi ...
- asp.net2.0中的ValidationGroup (转)
asp.net2.0中的ValidationGroup 在asp.net 1.1中,对于验证类控件,在使用时,遇到有的不需要验证的控件时,是十分麻烦的,就是说不可能有选择验证某些控件,而在asp.ne ...
最新文章
- java前台传多个id用什么接收_前端js传多个id 到java后台的处理方式
- 家电换新就现在 国美发放“年中惠民消费大补贴”
- MobaXterm无法退格删除,出现^H
- python中exception类的_什么是Python异常?Python异常的种类
- map 与 unordered_map
- LeetCode -- Merge Two Sorted Linked List
- 信息论与编码2 BCH码的构造
- 乱码转换器在线转换_有了这几款视频下载转换软件,想看的视频都可以随意看了...
- SpringBoot体验Mybatis、MybatisPlus、TKMybatis
- altium summer 9导入orcad dsn文件的方法
- 计算机usb显示不出来怎么办,U盘在电脑上显示不出来怎么办
- c语言中的三角函数公式,高中三角函数公式大全-必背基础知识点.doc
- win10系统登录和服务器,win10系统如何登录服务器地址
- 笔记本电脑没有鼠标怎么右键_没有鼠标怎么办?
- 文件上传中关于MultipartResolver的配置
- Vue 项目前端响应式布局及框架搭建
- python3 base64.b64decode Base64解码报错: Incorrect padding
- 验证码-kaptcha
- 如何选择IIOT数据采集解决方案:公有或私有?
- 标准化计算机考试软件,考易标准化电子试卷制作系统
热门文章
- layer normalization 缺点_优缺点并存的星越,用车感受还是不错的!
- Barh函数--Matplotlib
- ORACLE WebLogic Server 安装部署
- String类型的方法总结
- 简单实现ToolStripMenuItem(菜单栏)的单选效果
- 42、最大子序和(python)
- 钉钉机器人智能提醒_利用钉钉机器人和语雀提高协同办公效率
- 前端 encodeURI 为什么要编码两次
- JavaSE基础篇之-Java 流(Stream)、文件(File)和IO
- 计算机学院姚茜,武汉理工大学第三届届学位评定委员会