站长中国
设为首页 | 站长论坛

站长论坛 站长下载
您所在的位置: 站长中国 > 站长学院 > 网络编程 > NET专区 >  正文

 利用HttpModule做流量记录
  2008年02月20日14:34:46  评论(0条) 字体:[ ]
相关热点: 记录 流量 利用 /// public private /summary summary
    
  简单需求:
  记录用户访问网站的地址,浏览器,时间,用户信息等信息。
  
  原来打算用免费的流量统计系统,但是考虑到分析数据最好自己保留,所以最终决定自己做。首要一步就是记录流量信息。
  前面《利用HttpModule实现浏览器版本控制》就是在利用HttpModule记录流量信息时做的衍生,同时也可以实现页面编程无需任何附加代码。不需要加JS代码段也不要附加任何CS代码段。并且模块相互独立,可以重复利用,也利于不需要时分离。
  
  
  FlowEntity.cs(信息实体)——————————————————————————————————————————————
  using System;
  using System.Collections.Generic;
  using System.Text;
  
  namespace Xingmai.WebSite.FlowStatistics
  {
   /// <summary>
   /// 流量记录单个记录集
   /// </summary>
   public class FlowEntity
   {
   private FlowAgentEntity _AgentInfo;
   private FlowUserInfoEntity _UserInfo;
   private FlowRequestEntity _RequestInfo;
  
   /// <summary>
   /// 用户基本信息
   /// </summary>
   public FlowUserInfoEntity UserInfo
   {
   get
   {
   return _UserInfo;
   }
   set
   {
   _UserInfo = value;
   }
   }
  
   /// <summary>
   /// 用户代理信息
   /// </summary>
   public FlowAgentEntity AgentInfo
   {
   get
   {
   return _AgentInfo;
   }
   set
   {
   _AgentInfo = value;
   }
   }
  
   /// <summary>
   /// 用户访问信息
   /// </summary>
   public FlowRequestEntity RequestInfo
   {
   get
   {
   return _RequestInfo;
   }
   set
   {
   _RequestInfo = value;
   }
   }
   }
  
   /// <summary>
   /// 用户基本信息实体
   /// </summary>
   public class FlowUserInfoEntity
   {
   private int _UserID;
   private string _UserName;
  
   /// <summary>
   /// 用户ID
   /// </summary>
   public int UserID
   {
   get
   {
   return _UserID;
   }
   set
   {
   _UserID = value;
   }
   }
  
   /// <summary>
   /// 用户名
   /// </summary>
   public string UserName
   {
   get
   {
   return _UserName;
   }
   set
   {
   _UserName = value;
   }
   }
   }
  
   /// <summary>
   /// 用户代理信息实体
   /// </summary>
   public class FlowAgentEntity
   {
   private int _BrowserMajorVer;
   private double _BrowserMinorVer;
   private string _BrowserName;
   private string _HostName;
   private string _IP;
   private string _Language;
   private string _PlatForm;
  
   /// <summary>
   /// 用户访问IP
   /// </summary>
   public string IP
   {
   get
   {
   return _IP;
   }
   set
   {
   _IP = value;
   }
   }
  
   /// <summary>
   /// 用户主机名
   /// </summary>
   public string HostName
   {
   get
   {
   return _HostName;
   }
   set
   {
   _HostName = value;
   }
   }
  
   /// <summary>
   /// 用户语种
   /// </summary>
   public string Language
   {
   get
   {
   return _Language;
   }
   set
   {
   _Language = value;
   }
   }
  
   /// <summary>
   /// 用户操作系统平台
   /// </summary>
   public string PlatForm
   {
   get
   {
   return _PlatForm;
   }
   set
   {
   _PlatForm = value;
   }
   }
  
   /// <summary>
   /// 浏览器名称
   /// </summary>
   public string BrowserName
   {
   get
   {
   return _BrowserName;
   }
   set
   {
   _BrowserName = value;
   }
   }
  
   /// <summary>
   /// 浏览器主版本号
   /// </summary>
   public int BrowserMajorVer
   {
   get
   {
   return _BrowserMajorVer;
   }
   set
   {
   _BrowserMajorVer = value;
   }
   }
  
   /// <summary>
   /// 浏览器次版本号
   /// </summary>
   public double BrowserMinorVer
   {
   get
   {
   return _BrowserMinorVer;
   }
   set
   {
   _BrowserMinorVer = value;
   }
   }
   }
  
   /// <summary>
   /// 用户访问信息实体
   /// </summary>
   public class FlowRequestEntity
   {
   private DateTime _RequestDateTime;
   private string _RequestUrl;
  
   /// <summary>
   /// 访问时间
   /// </summary>
   public DateTime RequestDateTime
   {
   get
   {
   return _RequestDateTime;
   }
   set
   {
   _RequestDateTime = value;
   }
   }
  
   /// <summary>
   /// 访问地址
   /// </summary>
   public string RequestUrl
   {
   get
   {
   return _RequestUrl;
   }
   set
   {
   _RequestUrl = value;
   }
   }
   }
  }
  
  FlowModule.cs(Module模块)——————————————————————————————————————————————
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Web;
  using System.Xml;
  using System.IO;
  using System.Configuration;
  
  namespace Xingmai.WebSite.FlowStatistics
  {
   public class FlowModule : IHttpModule
   {
   #region 内部似有变量
  
   private string[] FlowType;
   private FlowDAL dal;
  
   #endregion
  
   #region 内部自有方法
  
   private bool IsFlowType(string strUrl)
   {
   foreach (string strFlowType in FlowType)
   {
   if (strUrl.ToLower().Contains(strFlowType))
   {
   return true;
   }
   }
   return false;
   }
  
  
   #endregion
  
   #region 实例构造函数
  
   public FlowModule()
   {
   //读取记录数据的类型
   try
   {
   FlowType = ConfigurationManager.AppSettings["FlowType"].Split((new string[] { "|" }), StringSplitOptions.RemoveEmptyEntries);
   }
   catch (System.Configuration.ConfigurationErrorsException ex)
   {
   throw new Exception(string.Format("请正确配置web.config AppSetting[BrowserChooserPage]节点,系统错误提示:{0}", ex.Message));
   }
   catch (System.Exception ex)
   {
   throw ex;
   }
   //实例化数据层
   dal = new FlowDAL();
   }
  
   #endregion
  
   #region IHttpModule 成员
  
  
   public void Init(HttpApplication application)
   {
   //这里8月29日有更改,这个BeginRequest事件里面无法获取到Session,疏忽,望大家谅解!应改用AcquireRequestState事件!
   //application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
   application.AcquireRequestState+=new EventHandler(application_AcquireRequestState);
   }
  
   private void application_AcquireRequestState(Object source, EventArgs e)
   {
   HttpApplication Application = (HttpApplication)source;
   HttpContext ctx = Application.Context;
  
   if(!IsFlowType(ctx.Request.Url.AbsoluteUri))
   return;
  
   FlowUserInfoEntity user = new FlowUserInfoEntity();
   if (ctx.Session["UserInfo"] != null)
   {
   user.UserID = 1;
   user.UserName = "ceshi";
   }
   else
   {
   user.UserID = 0;
   user.UserName = "UnKnown";
   }
  
   FlowRequestEntity request = new FlowRequestEntity();
   request.RequestDateTime = DateTime.Now;
   request.RequestUrl = ctx.Request.Url.AbsoluteUri;
  
   FlowAgentEntity agent = new FlowAgentEntity();
   agent.BrowserMajorVer = ctx.Request.Browser.MajorVersion;
   agent.BrowserMinorVer = ctx.Request.Browser.MinorVersion;
   agent.BrowserName = ctx.Request.Browser.Browser;
   agent.HostName = ctx.Request.UserHostName;
   agent.IP = ctx.Request.UserHostAddress;
   agent.Language = ctx.Request.UserLanguages[0];
   agent.PlatForm = ctx.Request.Browser.Platform;
  
   FlowEntity entity = new FlowEntity();
   entity.AgentInfo = agent;
   entity.UserInfo = user;
   entity.RequestInfo = request;
   dal.Record(entity);
   }
  
   public void Dispose()
   {
  
   }
  
   #endregion
   }
  }
  
  FlowDAL.cs(数据存储层,可以根据自己的需要重写此层。想存数据库也行,XML也行)—————————————————————————
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Data;
  using System.Data.Common;
  using System.Data.SqlClient;
  using System.Configuration;
  
  namespace Xingmai.WebSite.FlowStatistics
  {
   /// <summary>
   /// 流量统计数据层
   /// </summary>
   public class FlowDAL
   {
   private SqlConnection _conn;
  
   public FlowDAL()
   {
   try
   {
   _conn = new SqlConnection(ConfigurationManager.ConnectionStrings["FlowConn"].ConnectionString);
   _conn.Open();
   }
   catch (ConfigurationErrorsException ex)
   {
   throw new Exception(string.Format("请正确配置web.config AppSetting[BrowserChooserPage]节点,系统错误提示:{0}", ex.Message));
   }
   catch (SqlException ex)
   {
   throw ex;
   }
   catch (Exception ex)
   {
   throw ex;
   }
   }
   /// <summary>
   /// 记录流量信息
   /// </summary>
   /// <param name="flowEntity">流量记录实体</param>
   public void Record(FlowEntity flowEntity)
   {
   //判断连接是否为打开状态
   if (_conn.State = !ConnectionState.Open)
   _conn.Open();
  
   ///////记录代码略////////
   }
  
   public void Dispose()
   {
   _conn.Close();
   }
   }
  }
  
  web.config <system.web> <httpModules> 配置节点—————————————————————————————————
  <add name="FlowModule" type="Xingmai.WebSite.FlowStatistics.FlowModule, Xingmai.WebSite.FlowStatistics"/>
  
  web.config <appSettings> 配置节点 (需要记录的类型)——————————————————————————————
  <add key="FlowType" value=".htm|.html|.aspx|.asmx"/>
  
  web.config <connectionStrings>配置节点 (记录数据库的连接,如果你重写的数据层,那么这个可要可不要)——————
  <add name="FlowConn" connectionString="" providerName="System.Data.SqlClient"/>
  
  
  
  
  关于IHttpModule(MSDN信息)
  自定义 HTTP 模块阐释了 HTTP 模块的基本功能。在响应下面两个事件时调用该模块:BeginRequest 事件和 EndRequest 事件。这使该模块可以在处理页请求之前和之后运行。在这种情况下,
  
  该模块向请求的 ASP.NET 网页的任一 HTTP 请求开头处添加一条消息,并在处理请求后添加另一条消息。
  
  注意
  BeginRequest 和 EndRequest 事件只是在处理页期间发生的两个事件。有关在处理页期间引发的事件的更多信息,请参见 ASP.NET 网页中的服务器事件处理。
  
  每个事件处理程序都编写为模块的私有方法。在引发已注册事件时,ASP.NET 调用该模块中适当的处理程序方法,该方法将信息写入 ASP.NET 网页中。
  
  创建自定义 HTTP 模块类
  如果网站还没有 App_Code 文件夹,请在该站点的根目录下创建这样的一个文件夹。
  
  在 App_Code 目录中,创建一个名为 HelloWorldModule.cs的类文件。
  
  注意
  或者,可以将 HelloWorldModule 类编译到一个库中,并将得到的 .dll 文件放在 Web 应用程序的 Bin 目录中。
  
  将以下代码添加到该类文件中:
  
  C#
  public class HelloWorldModule : IHttpModule
  {
   public HelloWorldModule()
   {
   }
  
   public String ModuleName
   {
   get { return "HelloWorldModule"; }
   }
  
   // In the Init function, register for HttpApplication
   // events by adding your handlers.
   public void Init(HttpApplication application)
   {
   application.BeginRequest +=
   (new EventHandler(this.Application_BeginRequest));
   application.EndRequest +=
   (new EventHandler(this.Application_EndRequest));
   }
  
   private void Application_BeginRequest(Object source,
   EventArgs e)
   {
   // Create HttpApplication and HttpContext objects to access
   // request and response properties.
   HttpApplication application = (HttpApplication)source;
   HttpContext context = application.Context;
   context.Response.Write("<h1><font color=red>
   HelloWorldModule: Beginning of Request
   </font></h1><hr>");
   }
  
   private void Application_EndRequest(Object source, EventArgs e)
   {
   HttpApplication application = (HttpApplication)source;
   HttpContext context = application.Context;
   context.Response.Write("<hr><h1><font color=red>
   HelloWorldModule: End of Request</font></h1>");
   }
  
   public void Dispose()
   {
   }
  }
  
  注册 HTTP 模块
  在创建完 HelloWorldModule 类后,可以通过在 Web.config 文件中创建一项来注册该模块。
  
  在 Web.config 文件中注册该模块
  如果网站还没有 Web.config 文件,请在该站点的根目录下创建一个这样的文件。
  
  将下面突出显示的代码添加到该 Web.config 文件中:
  
   复制代码
  <configuration>
   <system.web>
   <httpModules>
   <add name="HelloWorldModule" type="HelloWorldModule"/>
   </httpModules>
   </system.web>
  </configuration>
  
  
  这段代码用 HelloWorldModule 的类名和模块名注册该模块。
  
  测试自定义 HTTP 模块
  创建并注册完自定义 HTTP 模块后,可以对它进行测试。
  
  测试自定义 HTTP 模块
  在应用程序中创建一个 Default.aspx 页。
  
  在浏览器中请求该 Default.aspx 页。
  
  HTTP 模块会将一个字符串追加到响应的开头和结尾。在请求扩展名指定为 ASP.NET 类型的文件时,该模块将会自动运行。
  
  
  
  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  后续《利用HttpModule做流量记录 补充》对方案进行了一些补充
  
  如果选用从Session中传入用户信息或者其他需要记录的信息,请在记录前加判断(2007年8月29日20:34:43增加)
   if (ctx.Handler is Page || ctx.Handler is WebService)
  根据需要选用Page还是WebService。
  调试过程中发现,如果是其他的类型可能不创建Session,这时从Session读取数据发生错误,造成整个请求中断引起请求失效。这样其他的Module可能不能执行造成页面上一些需要生成的东西无法生成,例如Asp.net Ajax从WebService生成的脚本类型注册等,引发错误!
  尽量捕捉错误,因为这些错误可能不会直接爆出,引发请求中断,让人有的时候摸不着头脑!
  
  
    做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。


责任编辑:

收藏本文 打印 打印本文  推荐本文 告诉好友 投稿 投稿邮箱

站长排行

学院

新闻

专栏

盈利

[揭密网络黄链]中国留学生买凶专破日本
JSP语法(6)
超强弹出窗口代码,什么都挡不住
FLASH视觉特效实例之地震效果
贴吧发帖机使用教程(绝对原创)
关于数据分页(转自www.codeproject.co
ASP实现文件直接下载
Photoshop制作光感超酷效果水晶球
 遍历ASP.NET页面控件
永远的后门[经典]+查不出的后门
淘宝网卖家公然叫卖“艳照门”照片集
驳《百度Hi面世对腾讯有利》
Google绿色专家质疑黑色背景网页节省资
国内各IT企业办公环境揭秘(多图)
阿里妈妈广告卖主全攻略
站长创业源动力 主流站长站赏析
推荐阅读:80年小子的创业道理
Discuz!6.0猛将出击 最强论坛程序酷炫
我的网络,我的团队:专访李文明
百度新闻频道改版十天 流量止跌反弹翻
ECSHOP模板制作参考文档
悬挂阿里妈妈会否被百度惩罚
阿里妈妈是否是中小站长的救世主?
最强网店ECShop发新版 众多酷炫功能给
ECSHOP模板下载
土豆网,优酷网,爆米花等视频网站采集
DedeCms模板安装/制作概述
网上商店系统巅峰对决 ECShop vs ShopE
艰难的走在创业的路上 第一天
编程中国全站采集规则
性福联盟 一个不尊重站长的联盟
大脚:日赚100元—揭露最新firefox欺骗
大脚:垃圾站超级赚钱法之二—突破“站
大脚:垃圾站超级赚钱法之——前言
迅雷联盟、快车联盟收入对比
经理人必看的十个管理网站
Google Adsense的秘密 第二版
西联汇款兑付城市查询
不用SEO取得成功的10个步骤
关于做GOOGLE的五条经验
站长学院  网页设计 建站教程 图形图象 网络编程

Photoshop CS3
Photoshop CS3
不用Photoshop
不用Photoshop

DIV+CSS的开发方式 听听另外的
虚拟主机建站动易里快速生成的
VBScript特效代码 满屏幕乱跑
牛气!一个菜鸟站长的超强网站
创建、维护一个个人博客的“投
让网站流量稳步飙升的秘籍
网站推广的基本思想

新闻线索

如果你有站长界人事变动、重组并购、变革技术出现,以及产品投诉等重要新闻线索,请告诉我们,我们会给予特别关注。
0631-3653338
站长中国编辑部
站长中国24小时新闻热线: 13256307008