当浏览器发送一个请求道服务器时, 实际上需要经过上图所示的流程, 该过程可以概括为:
"请求 ---> IIS ---> (检查IIS配置后)ASP.NET ---> HttContext ---> HttpApplication"
此时, 就进入了HttpApplication处理管道, 只要是ASP.NET的请求, 都会经过这个管道, 并且每一个请求都会经过这个处理管道. 而我们所熟悉的页面处理只是该流程第11步之后才开始执行的(Page_PreInit、Page_Init、Page_InitComplete、Page_PreLoad、Page_Load、Page_LoadComplete、Page_PreRender、Page_PreRenderComplete、SaveState、SaveStateComplete、Render), 而对于不同类型的文件(aspx、ashx、asmx等)则是在第7步之后进行选择的, 系统会根据文件扩展名, 为该文件映射对应的HttpHandler类.
我们实现HttpApplication的事件处理有两种方法: 即Global.aspx和IHttpModule两种方法, 更专业的方法是通过IHttpModule接口完成.
一: Globle.aspx
在Globle.aspx文件中, Application_Start方法将只能在应用程序调用第一个资源(如: 页面)时被执行, 且只能执行一次. 由于只能调用一次, 所以最好只设置静态数据(类成员), 不要设置实例数据, 因为实例数据只能有HttpAppliation类的第一个实例调用.
由于Application_Error可能发生在应用程序的任何阶段, 所以只有Application_end在应用程序生命周期最后会被调用且一定会被调用, 而Session_Start用于启动新会话, 注意: 只有当会话状态模式为"InProc"时, 才会引发Session_End时间, 其他模式(StateServer或SqlServer模式)将不会引发该事件.
//Default.aspx
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title ></ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:label ID ="lbl_time" runat ="server" text ="Label" ></ asp:label >
</ div >
</ form >
</ body >
</ html >
//Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
}
protected void Page_PreRender( object sender, EventArgs e)
{
// DateTime time = DateTime.Parse(this.Context.Items["begin"].ToString());
DateTime time = DateTime.Parse( this .Application[ " begin " ].ToString());
this .lbl_time.Text = " 页面累计运行时间为: " + (DateTime.Now - time).TotalMilliseconds.ToString() + " 毫秒! " ;
}
}
//Global.asax
<% @ Application Language = " C# " %>
< script runat = " server " >
void Application_Start( object sender, EventArgs e)
{
// Code that runs on application startup
DateTime begin = DateTime.Now;
// 使用HttpContext状态管理传递参数, 此种方法只能用一次, 由于Application_Start只执行一次, 新的HttpApplication对象无法使用
// HttpContext context = HttpContext.Current;
// context.Items["begin"] = begin;
this .Application[ " begin " ] = begin; // 保存到全局状态
}
void Application_End( object sender, EventArgs e)
{
// Code that runs on application shutdown
}
void Application_Error( object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
}
void Session_Start( object sender, EventArgs e)
{
// Code that runs when a new session is started
}
void Session_End( object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
}
</ script >
二: 通过HttpModule接口完成:
2.1 通过HttpModule实现页面时间
//default.aspx
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:Label ID ="lbl_pagetime" runat ="server" Text ="页面开销" ></ asp:Label >
</ div >
</ form >
</ body >
</ html >
//default.aspx.cs
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
System.Threading.Thread.Sleep( 5000 );
}
protected void Page_PreRenderComplete( object sender, EventArgs e)
{
DateTime end = DateTime.Now;
// HttpContext context = HttpContext.Current; // 这个时候有页面对象, 可以直接通过this.Context属性获得
TimeSpan span = end - this .Context.Timestamp;
this .lbl_pagetime.Text = string .Format( " aspx中处理---页面执行时间为: {0}毫秒 " ,span.TotalMilliseconds);
}
}
//web.config
< system .web >
< httpModules >
< add name ="PageTimeModule" type ="Page.PageTime" />
</ httpModules >
</ system.web >
//App_Code中PageTime.cs
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
namespace Page
{
/// <summary>
/// Summary description for PageTime
/// </summary>
public class PageTime : IHttpModule
{
// 方法1:
DateTime begin;
DateTime end;
public PageTime()
{
//
// TODO: Add constructor logic here
//
}
#region IHttpModule Members
public void Dispose()
{
// 没有什么资源要清空
}
public void Init(HttpApplication application) // 避免与HttpContext混淆, 改名
{
application.BeginRequest += new EventHandler(Application_BeginRequest); // 在管道的第一个事件中注册
application.EndRequest += new EventHandler(Application_EndRequest); // 管道的最后一个事件
}
void Application_EndRequest( object sender, EventArgs e)
{
// throw new NotImplementedException();
end = DateTime.Now;
TimeSpan span = end - begin;
HttpContext context = HttpContext.Current;
System.IO.TextWriter tw = context.Response.Output;
tw.WriteLine( string .Format( " 执行事件为: {0} 毫秒! " , span.TotalMilliseconds));
// 方法2:
DateTime begin1 = context.Timestamp;
DateTime end1 = DateTime.Now;
TimeSpan span2 = end - begin;
tw.WriteLine( string .Format( " 执行事件为: {0} 毫秒! " , span.TotalMilliseconds));
}
void Application_BeginRequest( object sender, EventArgs e)
{
// throw new NotImplementedException();
begin = DateTime.Now;
}
#endregion
}
}
2.2 通过HttpModule实现用户登陆的状态管理
//LoginModel.cs, HttpModule接口实现类
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
namespace Login
{
/// <summary>
/// Summary description for LoginModule
/// </summary>
public class LoginModule : IHttpModule
{
public LoginModule()
{
//
// TODO: Add constructor logic here
//
}
#region IHttpModule Members
public void Dispose()
{
// throw new NotImplementedException();
}
public void Init(HttpApplication application)
{
// throw new NotImplementedException();
application.AuthenticateRequest += new EventHandler(Application_AuthenticateRequest); // 在管道中处理AuthenticateRequest事件
}
void Application_AuthenticateRequest( object sender, EventArgs e)
{
// throw new NotImplementedException();
HttpContext context = HttpContext.Current;
HttpCookie cookie = context.Request.Cookies[ " UserName " ]; // 查看是否存在cookie
if (cookie != null )
{
// 从cookie中取出名字, 放到context中, 以便在PreRequestHandlerExecute之后执行的页面处理事件中获得其中的值
string name = cookie.Value;
context.Items[ " loggedname " ] = name;
}
}
#endregion
}
}
//default.aspx
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:Label ID ="lbl_welcome" runat ="server" Text ="欢迎信息! " ></ asp:Label >
< asp:LinkButton ID ="lbtn_loggout" runat ="server" onclick ="lbtn_loggout_Click" > 注销 </ asp:LinkButton >
< asp:HyperLink ID ="hlnk_loggin" runat ="server" NavigateUrl ="~/Login.aspx" > 登陆 </ asp:HyperLink >
</ div >
</ form >
</ body >
</ html >
//default.aspx.cs
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
if ( this .Context.Items[ " loggedname " ] != null )
{
this .lbl_welcome.Text = string .Format( " {0}, 您好! 欢迎回来! " , this .Context.Items[ " loggedname " ]);
this .hlnk_loggin.Visible = false ;
this .lbtn_loggout.Visible = true ;
}
else
{
this .lbl_welcome.Text = string .Format( " 对不起, 您还没有登录! " );
this .lbtn_loggout.Visible = false ;
this .hlnk_loggin.Visible = true ;
}
}
protected void lbtn_loggout_Click( object sender, EventArgs e)
{
HttpCookie cookie = this .Request.Cookies[ " UserName " ]; // 从请求里找cookie
cookie.Expires = new DateTime( 1900 , 1 , 1 );
this .Response.SetCookie(cookie); // 重新设置cookie
this .Response.Redirect( " Login.aspx " );
}
}
//login.aspx
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Login.aspx.cs " Inherits = " Login " %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< span > 用户名: </ span >
< asp:TextBox ID ="txt_username" runat ="server" ></ asp:TextBox >< br />
< span > 密码: </ span >
< asp:TextBox ID ="txt_userpass" runat ="server" ></ asp:TextBox >< br />
< hr />
< asp:CheckBox ID ="chkBox_remember" runat ="server" Text ="长期登陆" />< br />
< asp:LinkButton ID ="lbtn_login" runat ="server" onclick ="lbtn_login_Click" > 登陆 </ asp:LinkButton >
</ div >
</ form >
</ body >
</ html >
//login.aspx.cs
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class Login : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
}
protected void lbtn_login_Click( object sender, EventArgs e)
{
string username = this .txt_username.Text;
string userpass = this .txt_userpass.Text;
if (username != null && userpass != null )
{
DAL.CalendarUser calendar = new DAL.CalendarUser();
if (calendar.ValidateUserByProc(username, userpass))
{
HttpCookie cookie = new HttpCookie( " UserName " );
cookie.Value = username;
if ( this .chkBox_remember.Checked == true )
{
cookie.Expires = DateTime.Now.AddDays( 7 );
}
this .Response.Cookies.Add(cookie); // 发cookie给可户端
this .Response.Redirect( " default.aspx " ); // 重定向到default.aspx
}
}
}
}
//web.config
< system.web >
< httpModules >
< add name ="ScriptModule" type ="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
< add name ="LoginModule" type ="Login.LoginModule" />
</ httpModules >
</ system.web >
//DAL- Calendar.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DAL
{
public class CalendarUser // DAL层通过SqlHelper访问数据库
{
// CalendarUser类提供关于日历用户的功能, 如: 创建用户
// DateTime是值类型, 而值类型没有与Sql中Null的对应, 加?表示可空类型, 即允许值类型为空
public int CreateUser( string username, string userpass, string email, DateTime ? birthday)
{
int result = - 1 ;
// 定制的参数是根据SqlHelper的方法来选的
string connectionStr = CalendarHelper.ConnectionString;
string sqlText = @" insert into T_UserInfo(username, userpass,email,birthday)
values(@username,@userpass,@email,@birthday) " ;
System.Data.CommandType cmdType = System.Data.CommandType.Text;
System.Data.SqlClient.SqlParameter p_username = new System.Data.SqlClient.SqlParameter( " @username " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_userpass = new System.Data.SqlClient.SqlParameter( " @userpass " ,System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_email = new System.Data.SqlClient.SqlParameter( " @email " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_birthday = new System.Data.SqlClient.SqlParameter( " @birthday " ,System.Data.SqlDbType.DateTime);
p_username.Value = username;
p_userpass.Value = userpass;
p_email.Value = email;
p_birthday.Value = birthday;
System.Data.SqlClient.SqlParameter[] paras
= new System.Data.SqlClient.SqlParameter[] { p_username, p_userpass, p_email, p_birthday };
result = Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteNonQuery(connectionStr, cmdType,sqlText, paras);
return result;
}
public int CreateUserByProc( string username, string userpass, string email, DateTime ? birthday)
{
// 定制的参数是根据SqlHelper的方法来选的
string connectionStr = CalendarHelper.ConnectionString;
string sqlText = " SP_CreateUserProc " ;
System.Data.CommandType cmdType = System.Data.CommandType.StoredProcedure;
System.Data.SqlClient.SqlParameter p_username = new System.Data.SqlClient.SqlParameter( " @username " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_userpass = new System.Data.SqlClient.SqlParameter( " @userpass " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_email = new System.Data.SqlClient.SqlParameter( " @email " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_birthday = new System.Data.SqlClient.SqlParameter( " @birthday " , System.Data.SqlDbType.DateTime);
System.Data.SqlClient.SqlParameter p_return = new System.Data.SqlClient.SqlParameter( " @returnValue " ,System.Data.SqlDbType.Int);
p_username.Value = username;
p_userpass.Value = userpass;
p_email.Value = email;
p_birthday.Value = birthday;
p_return.Direction = System.Data.ParameterDirection.ReturnValue;
System.Data.SqlClient.SqlParameter[] paras
= new System.Data.SqlClient.SqlParameter[] { p_username, p_userpass, p_email, p_birthday,p_return};
Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteNonQuery(connectionStr, cmdType, sqlText, paras);
// 执行完存储过程后, 获取返回值
return ( int )p_return.Value;
}
public bool ValidateUserByProc( string username, string userpass)
{
// 定制的参数是根据SqlHelper的方法来选的
string connectionStr = CalendarHelper.ConnectionString;
string sqlText = " SP_ValidateUserByProc " ;
System.Data.CommandType cmdType = System.Data.CommandType.StoredProcedure;
System.Data.SqlClient.SqlParameter p_username = new System.Data.SqlClient.SqlParameter( " @username " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_userpass = new System.Data.SqlClient.SqlParameter( " @userpass " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_return = new System.Data.SqlClient.SqlParameter( " @returnValue " , System.Data.SqlDbType.Int);
p_username.Value = username;
p_userpass.Value = userpass;
p_return.Direction = System.Data.ParameterDirection.ReturnValue;
System.Data.SqlClient.SqlParameter[] paras
= new System.Data.SqlClient.SqlParameter[] { p_username, p_userpass, p_return };
Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteNonQuery(connectionStr, cmdType, sqlText, paras);
// 执行完存储过程后, 获取返回值
return ( int )p_return.Value == 1 ; // 返回1表示不存在, 即验证成功
}
}
}
//CalendarHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DAL
{
public class CalendarHelper // 为DAL层提供连接串
{
private static readonly string connectionStr = System.Configuration.ConfigurationManager.ConnectionStrings[ " MsSql " ].ConnectionString;
public static string ConnectionString // 对外提供连接串
{
get
{
return connectionStr;
}
}
}
}
//SqlHelp.cs, 可以到网上去下载