我们在开发企业Web应用程序时经常需要对用户的操作记录日志,以便在发生突发事件后有据可查,比如要对用户访问的每一个页面都做日志记录。通常的做法可能是编写一个记录日志的方法(如:AddAccessLog),在每一个页面的Page_Load事件中调用这个AddAccessLog方法,从而达到记录页面访问日志的目的。这样的方法在页面较少的时候可行,但是当项目变得越来越大,需要记录日志的页面越来越多的时候,我们要在每个页面中都调用这样的方法,从而使得系统很难维护。有没有简单一点的办法呢,何不用IHttpModule接口实现一个自定义的LogHttpModule来试试呢?

IHttpModule接口中定义了两个方法:Init和Dispose。Init方法初始化一个模块,并为它做好处理请求的准备。这时,我们同意接受感兴趣的事件通知。Dispose方法处置该模块使用资源。Init方法接受一个服务该请求的HttpApplication对象的引用。使用该引用可以连接到系统事件。

class PageLoggerModule : IHttpModule  //实现IHttpModule接口
{

public void Dispose()
{
}

public void Init(HttpApplication context)
{
    context.BeginRequest += new EventHandler(context_BeginRequest);
}

void context_BeginRequest(object sender, EventArgs e)
{

//在这里实现具体代码

HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context;

//acquire session state
string userId = "Not Registered";
if (ctx.Session != null && ctx.Session["userId"] != null)
{
    userId = ctx.Session["userId"].ToString();
}

//acquire request string
string funcId = "Init funcId";
if (ctx.Request.QueryString["funcId"] != null)
{
    funcId = ctx.Request.QueryString["funcId"].ToString();
}

LogEntry log = new LogEntry(); // 这里是自定义的一个类,属性列表和数据库中的字段一致
log.DateTime = System.DateTime.Now;
log.IpAddress = ctx.Request.UserHostAddress;
log.MachineName = ctx.Request.UserHostName;
log.UserId = userId;
log.FunctionId = funcId;

string logString = log.DateTime.ToString() + "<br/>"
+ log.UserId + "<br/>"
+ log.IpAddress + "<br/>"
+ log.MachineName + "<br/>"
+ log.FunctionId + "<br/>";

//you can add other codes here
ctx.Response.AppendHeader("Author", "Changyu Du");

ctx.Response.Write(logString);

}

}

在Web.config中,System.Web节中增加一个HttpModule:

<httpModules>
       <add name="PageLoggerHttpModule" type="PageLoggerHttpModule.PageLoggerModule,PageLoggerHttpModule"/>
    </httpModules>

新建一个普通的aspx页面,在页面加载时把用户信息保存到Session中,模拟一下项目应用中的情形:

protected void Page_Load(object sender, EventArgs e)
{
    //Add userName into SESSION
    if (Session["userId"] == null)
    {
        Session["userId"] = "1101";
    }
    else
    {
        Response.Write("SESSION :userId = "+Session["userId"].ToString());
    }
}

为了确保把用户Id信息加入到session中,测试页面上还随便加了个button,button_click什么都不干,就是为了让页面回发一下确保把userId存入到Session中去。F5运行一下,嗯,不错,LogEntry的信息都输出出来了,已经取得了访问时间,IP地址之类的信息,基本成功!下来直接把LogEntry的信息保存到数据库就OK了。

可是,别忙,怎么总取不到Session中的用户信息呢?记录访问日志用户Id这样的信息肯定是需要记录的啊!

后来放狗一搜才发现,还是对aspnet的事件处理流程不理解,Begin_Request时还没有加载Session状态呢,自然就取不到了。

下面是MSDN上提供的事件触发顺序:

在处理该请求时将由 HttpApplication 类执行以下事件。希望扩展 HttpApplication 类的开发人员尤其需要注意这些事件。

  1. 对请求进行验证,将检查浏览器发送的信息,并确定其是否包含潜在恶意标记。有关更多信息,请参见 ValidateRequest 和脚本侵入概述。

  2. 如果已在 Web.config 文件的 UrlMappingsSection 节中配置了任何 URL,则执行 URL 映射。

  3. 引发 BeginRequest 事件。

  4. 引发 AuthenticateRequest 事件。

  5. 引发 PostAuthenticateRequest 事件。

  6. 引发 AuthorizeRequest 事件。

  7. 引发 PostAuthorizeRequest 事件。

  8. 引发 ResolveRequestCache 事件。

  9. 引发 PostResolveRequestCache 事件。

  10. 根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现 IHttpHandler 的类,对请求进行处理。如果该请求针对从 Page 类派生的对象(页),并且需要对该页进行编译,则 ASP.NET 会在创建该页的实例之前对其进行编译。

  11. 引发 PostMapRequestHandler 事件。

  12. 引发 AcquireRequestState 事件。

  13. 引发 PostAcquireRequestState 事件。

  14. 引发 PreRequestHandlerExecute 事件。

  15. 为该请求调用合适的 IHttpHandler 类的 ProcessRequest 方法(或异步版 BeginProcessRequest)。例如,如果该请求针对某页,则当前的页实例将处理该请求。

  16. 引发 PostRequestHandlerExecute 事件。

  17. 引发 ReleaseRequestState 事件。

  18. 引发 PostReleaseRequestState 事件。

  19. 如果定义了 Filter 属性,则执行响应筛选。

  20. 引发 UpdateRequestCache 事件。

  21. 引发 PostUpdateRequestCache 事件。

  22. 引发 EndRequest 事件。

AcquireRequestState事件,当实际服务请求的处理程序获得与该请求关联的状态信息时发生。在这个事件发生时才能取到Session中是userId信息。BeginRequest事件在AcquireRequestState之前发生,我们把取Session状态的代码放在BeginRequest中肯定是取不到的。

问题找到了,把日志记录代码放在AcquireRequestState中就可以了,于是改成下面的样子:

public void Init(HttpApplication context)
{
    context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
}

void context_AcquireRequestState(object sender, EventArgs e)
{

//原先context_BeginRequest中的代码,不重复贴占地方了 :)

//把LogEntry中的信息保存到数据库

}

好了,这样我们继承了IHttpModule接口,实现了一个自定义的LogMudule,这样在用户方面每个页面时,都会自动记录用户的信息记如访问日志数据库中,再也不用到每个页面的Page_Load中去写了,维护起来也方便多了! Yeah~

为方便我把源代码贴出来吧:其中保护我上一片blog《自己编写BuildProvider来实现ORM以及BuildProvider的调试》的代码:

CustomBuilderProvider.rar       299KB      2008/3/7 22:07:36
Download

转载于:https://www.cnblogs.com/junqilian/archive/2008/03/07/1095454.html

实现IHttpModule接口获取Session来实现页面访问日志功能。相关推荐

  1. 获取linux samba的文件访问日志

    一天一客户打电话说其公司的某一个共享文件夹完全不见,赶到客户处,经过分析,发现是因为某部门的同事不小心将之移动到其它的位置,把客户给吓得半 死.后来同其商量,为了解决此种,以及出现问题之后可以快速找出 ...

  2. 如何在ashx页面获取Session值(未将对象引用设置到对象的实例) (转)

    如何在ashx页面获取Session值(未将对象引用设置到对象的实例) 分类: .Net学习笔记 Session 2011-11-30 10:25 902人阅读 评论(1) 收藏 举报 在一般事务处理 ...

  3. Jsp页面获取session

    关于jsp页面获取session的方式: 假如有这样一个session值:(name: 'tomcat') 1.用stracts获取: <s:property value="#sess ...

  4. java Corba北向接口连接创建 获取session工厂

    之前在网上查询较多连接方法无法建立正确连接,参考无数文档后找到了自己的方法,以助于其他小伙伴们少走弯路.出处不太记得了不贴了.(相关的java类是华为北向接口类可查询下载) 初始化方法如下 publi ...

  5. Python爬虫:百度翻译接口获取翻译结果

    分析百度翻译接口,使用python获取翻译结果 目标:获取百度翻译结果 工具:chrome/firefox浏览器.pychram.python3.7 模块:requests.re.execjs 开始分 ...

  6. 【javaweb】Session原理以及浏览器禁止Cookie之后服务器如何获取Session

    在web应用中打开浏览器访问一个网站,登录,浏览,到关闭浏览器,称为是一个会话.由于Http协议是无状态的,因此用户在动态页面交互信息需要一些能够保存用户信息的数据结构.这个保存用户浏览数据的数据结构 ...

  7. 在一般处理程序(handler)中获取session的方法

    这些天做用户实施警告系统 其中在完成时时监控的时候 ,由于需要时时监控网站的所有用户信息 但是在一般处理程序中想要获取session状态但是抛出异常说上下文中不存在session 在 aspx和asp ...

  8. html中加session,Html中如何获取session中的值(如登录后显示XX欢迎您!)

    话不多说,直接切入正题. 相信大家经常在各大网站上,登录过自己的帐号吧,那么就一定应该见过在点击登录之后,会发现在top的顶部状态栏中或是页面中央显示着 "xx欢迎您!"之类的语句 ...

  9. php网页跳转无法获取session值

    今日编写项目,需要在跳转后的页面获取session值进行自动登录操作,但是明明在传输页面可以打印出session值,但在接受页面却显示session值为空,经确认脚本中的session_start() ...

最新文章

  1. Regular in UltraEdit
  2. 【PPT下载】第二批PPT干货限时免费分享
  3. 洛谷 P2935 [USACO09JAN]最好的地方Best Spot
  4. JQuery 动画卷页 -- 返回顶部 动画特效(兼容Chrome)
  5. v8学习笔记(七) 执行过程
  6. 学习vi和vim编辑器(8):全局替换(1)
  7. 一般一个前端项目完成需要多久_一种按周迭代的敏捷式项目管理方法
  8. echarts 有引导线和内部文字_点、线、面构图的异同以及相互转化
  9. 安卓camera总体框架
  10. 【Itext】7步制作Itext5页眉页脚pdf实现第几页共几页
  11. mysql 根据子查询的结果查询朱标_Python - MySQL数据库操作
  12. coin collector(一道测试题)
  13. 和root权限挣扎过的一些记录
  14. 刘徽割圆法转化成matlab,刘徽割圆术动画演示
  15. oracle 批量生成约束,关于sql脚本导入Oracle时重复生成check约束的问题解决
  16. SitePoint播客#160:坐在树上的Adobe和HTML
  17. 计算机怎么禁止远程桌面,win7怎样禁用远程桌面共享_win7系统禁用远程桌面共享的步骤-系统城...
  18. 清华大学python教材怎么样_经典!清华大学计算机系教材曝光:《Python编程金典》...
  19. Clouda框架:入门全过程之安装使用
  20. 从产品的特点看产品思维

热门文章

  1. [Codevs] 1001 舒适的路线
  2. PHP快速入门 如何操作MySQL
  3. xcode编译项目Permission denied错误
  4. 正尝试安装的adobe flash player不是最新版本
  5. 企业级 SpringBoot 教程 (四)SpringBoot 整合JPA
  6. 往hdfs写数据无权限
  7. 记一次支付系统的设计体验
  8. rsync 安装使用详解
  9. 生成Rss聚合页xml内容信息
  10. datagrid单选多选