实现IHttpModule接口获取Session来实现页面访问日志功能。
我們在開發(fā)企業(yè)Web應用程序時經常需要對用戶的操作記錄日志,以便在發(fā)生突發(fā)事件后有據可查,比如要對用戶訪問的每一個頁面都做日志記錄。通常的做法可能是編寫一個記錄日志的方法(如: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節(jié)中增加一個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什么都不干,就是為了讓頁面回發(fā)一下確保把userId存入到Session中去。F5運行一下,嗯,不錯,LogEntry的信息都輸出出來了,已經取得了訪問時間,IP地址之類的信息,基本成功!下來直接把LogEntry的信息保存到數據庫就OK了。
可是,別忙,怎么總取不到Session中的用戶信息呢?記錄訪問日志用戶Id這樣的信息肯定是需要記錄的啊!
后來放狗一搜才發(fā)現,還是對aspnet的事件處理流程不理解,Begin_Request時還沒有加載Session狀態(tài)呢,自然就取不到了。
下面是MSDN上提供的事件觸發(fā)順序:
| 在處理該請求時將由 HttpApplication 類執(zhí)行以下事件。希望擴展 HttpApplication 類的開發(fā)人員尤其需要注意這些事件。 對請求進行驗證,將檢查瀏覽器發(fā)送的信息,并確定其是否包含潛在惡意標記。有關更多信息,請參見 ValidateRequest 和腳本侵入概述。 如果已在 Web.config 文件的 UrlMappingsSection 節(jié)中配置了任何 URL,則執(zhí)行 URL 映射。 引發(fā) BeginRequest 事件。 引發(fā) AuthenticateRequest 事件。 引發(fā) PostAuthenticateRequest 事件。 引發(fā) AuthorizeRequest 事件。 引發(fā) PostAuthorizeRequest 事件。 引發(fā) ResolveRequestCache 事件。 引發(fā) PostResolveRequestCache 事件。 根據所請求資源的文件擴展名(在應用程序的配置文件中映射),選擇實現 IHttpHandler 的類,對請求進行處理。如果該請求針對從 Page 類派生的對象(頁),并且需要對該頁進行編譯,則 ASP.NET 會在創(chuàng)建該頁的實例之前對其進行編譯。 引發(fā) PostMapRequestHandler 事件。 引發(fā) AcquireRequestState 事件。 引發(fā) PostAcquireRequestState 事件。 引發(fā) PreRequestHandlerExecute 事件。 為該請求調用合適的 IHttpHandler 類的 ProcessRequest 方法(或異步版 BeginProcessRequest)。例如,如果該請求針對某頁,則當前的頁實例將處理該請求。 引發(fā) PostRequestHandlerExecute 事件。 引發(fā) ReleaseRequestState 事件。 引發(fā) PostReleaseRequestState 事件。 如果定義了 Filter 屬性,則執(zhí)行響應篩選。 引發(fā) UpdateRequestCache 事件。 引發(fā) PostUpdateRequestCache 事件。 引發(fā) EndRequest 事件。 |
AcquireRequestState事件,當實際服務請求的處理程序獲得與該請求關聯的狀態(tài)信息時發(fā)生。在這個事件發(fā)生時才能取到Session中是userId信息。BeginRequest事件在AcquireRequestState之前發(fā)生,我們把取Session狀態(tài)的代碼放在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《自己編寫B(tài)uildProvider來實現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来实现页面访问日志功能。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串MD5加密和产生一个随机密码的方法
- 下一篇: LINQ体验系列文章导航