• 学习笔记HttpApplication处理管道


    当浏览器发送一个请求道服务器时, 实际上需要经过上图所示的流程, 该过程可以概括为:
    "请求 ---> 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, 可以到网上去下载

  • 相关阅读:
    Linux运维常用命令总结
    Leetcode: Capacity To Ship Packages Within D Days
    Leetcode: Stream of Characters
    Leetcode: Backspace String Compare
    Leetcode: Shortest Way to Form String
    Leetcode: Campus Bikes II
    Leetcode: Minimum Domino Rotations For Equal Row
    Leetcode: Palindromic Substrings
    Summary: curated List of Top 75 LeetCode Questions to Save Your Time
    Leetcode: Subtree of Another Tree
  • 原文地址:https://www.cnblogs.com/cs_net/p/1883706.html
Copyright © 2020-2023  润新知