新手学ASP.NET 3.5网络开发
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3 ASP.NET核心对象

正如上一章所讲的,ASP.NET的一个主要特征就是一切皆为对象。其中,有几个对象非常重要,许多工作都需要使用到。本章将介绍这几个影响ASP.NET应用工作的核心对象,包括Page、Server、Application,以及Session对象。

3.1 Page类

在用ASP.NET创建的Web系统中,每一个ASPX页面都继承自System.Web.UI.Page类,Page类实现了所有页面最基本的功能,本节介绍其基本概念及一个最简单的应用。

3.1.1 Page类概述

要理解Page类,首先需要了解Web服务器(IIS)是如何请求ASP.NET页面,并显示在浏览器上的。在浏览器显示ASPX页面的整个过程中,IIS负责处理与.NET Framework交互的大量工作。图3.1所示的是用户在浏览器上请求调用ASP.NET页面的响应过程。

图3.1 浏览器显示ASPX页面的响应过程

1 IIS 将接收这个请求,并识别出将要请求的文件类型为ASPX 文件,然后让ASP.NET 模块(aspnet isapi.dll)来处理它。

2 aspnet isapi.dll接收请求,将所请求的页面实例化为一个ASPX对象,并调用该对象的显示方法。该方法动态生成HTML,并返回给IIS。

3 IIS将HTML发送给浏览器。

这个过程中最重要的对象是ASPX对象,它继承自.NET Framework类库的Page类。也可以简单把Page对象理解为.aspx文件,在页面上,可以使用Page类的属性和方法完成一定的功能。

Page类位于System.Web.UI命名空间下,其常用成员如图3.2所示。

图3.2 Page类常用成员

Page类常用成员简单介绍如表3.1所示。

表3.1 Page类常用成员简单介绍

其中,Request、Response、Server、Application、Session对象,都是Page类的属性,将在本章后面各节中给予介绍。它们都依附于具体的一个Page对象,即依附于ASPX页面,而不能单独使用。

3.1.2 探索页面生命周期

【本节示例参考:\示例代码\C03\Page_LifeCycle】

一般来说,一个ASPX页面从“生”到“死”,要经历如图3.3所示的生命周期。前面已经简单介绍过,这里详细说明。

图3.3 ASPX页面生命周期

(1)请求页面:页请求发生在页生命周期开始之前。

(2)开始:在开始阶段,将设置页属性,如Request和Response。在此阶段,页面还将确定请求是回发请求还是新请求,并设置IsPostBack属性。

(3)初始化页面:页面初始化期间,可以使用页中的控件,并将设置每个控件的UniqueID属性。如果当前请求是回发请求,则回发数据尚未加载,并且控件属性值尚未还原为视图状态中的值。

(4)加载页面:加载期间,如果当前请求是回发请求,则将使用从视图状态和控件状态恢复的信息加载控件属性。

(5)验证:在验证期间,将调用所有验证程序控件的Validate方法,此方法将设置各个验证程序控件和页的IsValid属性。

(6)回发事件处理:如果请求是回发请求,则将调用所有事件处理程序。

(7)呈现页面:在页面呈现期间,视图状态将被保存到页面,然后页面将调用每个控件,以将其呈现的输出提供给页的Response属性的OutputStream。

(8)卸载页面:完全呈现页、将页发送至客户端并准备丢弃时,将调用卸载。此时,将卸载页属性(如Response和Request)并执行清理。

与上面的生命周期相对应的Page类的生命周期事件如图3.4所示。

图3.4 Page类生命周期事件

Page类生命周期中各个事件的说明如表3.2所示。

表3.2 Page类的生命周期事件

下面的示例说明了Page类的生命周期事件触发顺序。示例的实现很简单,在Default.aspx页面的各个事件中,输出其事件名称即可。以PreInit事件为例,其默认的事件名为Page PreInit,其余事件与此相同。代码3-1为PreInit事件的方法。

代码3-1 PreInit事件方法:Default.cs

    1.   int i=1;
    2.
    3.   ///<summary>
    4.   ///1:PreInit事件
    5.   ///</summary>
    6.   ///<param name="sender"></param>
    7.   ///<param name="e"></param>
    8.   protected void Page_PreInit(object sender,EventArgs e)
    9.   {
    10.     Page.Response.Write(i+":PreInit...<br/>");
    11.     i++;
    12.  }

其余事件的方法与此非常类似,不再一一给出。运行程序后,结果如图3.5所示。页面上依次显示了各个事件的触发顺序。

图3.5 Page类各个生命周期事件的触发顺序

3.2 ASP.NET核心对象

本节将介绍ASP.NET中最重要的几个对象:

(1)Response:向浏览器输出信息。

(2)Request:管理访问者对页面的请求信息。

(3)Server:提供一些与Web服务器相关的信息。

这几个对象总是依赖于具体的一个Page类,总是作为Page类的某个属性出现,下面将逐一介绍它们的常用功能。

3.2.1 利用Response输出信息

【本节示例参考:\示例代码\C03\ Example_Response】

Response对象是System.Web.HttpResponse类的实例,主要功能是向浏览器输出信息,常用的属性和方法如图3.6所示。

图3.6 Response对象常用属性和方法

Response对象常用成员简单介绍如表3.3所示。

表3.3 Response对象常用成员简单介绍

下面的示例中,将使用页面的Response属性向浏览器输出字符串“Hello”,然后换行后再输出“World”。

1 新建一个ASP.NET应用程序,双击自动添加的Default.aspx页面,在自动生成的页面加载事件中,输入如下代码。

代码3-2 利用Response输出字符串:Default.cs

    1.   protected void Page_Load(object sender,EventArgs e)
    2.   {
    3.      Response.Write("Hello<br/>");
    4.      Response.Write("World");
    5.   }

2 启动程序,将出现页面Default.aspx,如图3.7所示。

图3.7 使用Response对象向页面输出数据

可以看出,使用Response对象的Write方法可以向浏览器输出HTML元素,这样就有可能根据用户的响应,动态构建网页元素。

3.2.2 利用Request获取页面输入

【本节示例参考:\示例代码\C03\ Example_Request】

动态网页的最主要特征就是用户可以在网页上进行操作,向系统提交各种数据。对于ASPX页面来说,它利用其Request对象来接收和管理用户对页面的请求信息。

具体来说,当用户打开Web浏览器访问.aspx页面时,Web服务器就会收到其HTTP请求。请求信息既包括用户的请求方式(如POST、GET)、参数名、参数值等,又包括客户端的基本信息(如浏览器类型、版本号、用户所用语言及编码方式等),这些信息将被整合在一起。通过Request对象,便可以访问这些数据。Request对象的属性和方法比较多,常用的如图3.8所示。

图3.8 Request对象常用属性和方法

Request对象常用成员简单介绍如表3.4所示。

表3.4 Request对象常用成员简单介绍

Request对象的功能就是从客户端得到数据。常用的两种取得数据的方法是Request.Form和Request.QueryString,对应于Form提交时的POST和GET方法。

说明

GET方法将提交的数据构造成为URL的一部分传递给服务器,如常见的网址www.php.net/cal.php?id=1934中的“?id=1934”部分就是GET方法提交的数据。POST方法不会像GET那样把提交的数据暴露在浏览器的地址栏中。

下面的示例中,将使用页面的Request属性输出一系列用户操作信息。为了便于说明,本节将使用到两个常用的服务器控件:文本框(TextBox)和按钮(Button),分别用于接收用户的文本输入和提交动作。本书将在第15章中详细介绍这二者,此处,读者只需掌握其基本功能即可。

○文本框():用于接收用户输入信息;

○ 按钮():用户结束输入时的提交命令。

1 新建一个ASP.NET应用程序,然后从工具栏中拖放3个控件(1个文本框+2个按钮)到默认页面(Default.aspx)中,修改按钮的Text属性,将两个按钮的显示文本分别改为“POST”和“GET”,如图3.9所示。

图3.9 Request示例中的控件

2 双击“GET”按钮,在自动生成的按钮单击事件中,输入代码:

    Response.Redirect("Default.aspx?value=TestGetValue");

其功能为将页面重定向到“Default.aspx?value=1”。其中,页面“Default.aspx”表示所要跳转到的页面,“?”后面的串“value=1”表示使用GET方法提交的用户信息。

3 双击“POST”按钮,可为其增加单击事件,但无须在自动生成的按钮单击事件中输入任何代码。

4 双击Default.aspx页面,在自动生成的页面加载事件中,输入代码:

    1.   Response.Write(Request.Form["TextBox1"]);
    2.   Response.Write(Request.QueryString["value"]);

其中,第1行使用Request.Form属性,输出通过POST方式传递的用户信息;第2行使用Request.QueryString属性,输出通过GET方式提交的信息。这两个属性都是一个数组,可以通过索引或键值来获取数据。通常使用键值的方式,键值就是POST方式中的输入按钮ID(如TextBox1)或GET方式中的数据键值(如value)。

5 启动程序,将出现页面Default.aspx,在输入框中输入一些数据,然后单击“POST”按钮后,页面将显示所输入的数据,如图3.10所示。

图3.10 使用POST方式向页面提交数据

这个过程中,输入的数据首先通过POST方式传递给IIS,IIS让.NET来处理,.NET框架中的Request对象便接收这些数据,存储在Page.Request对象内部。

除了提交的数据之外,Request对象还能够得到其他的用户信息,例如,在页面加载事件中添加如下代码:

    1.   //其他用户信息
    2.   Response.Write(Request.Browser.Platform+"<br>");       //用户操作系统
    3.   Response.Write(Request.UserHostAddress+"<br>");       //用户网络地址
    4.   Response.Write(Request.UserLanguages[0]+"<br>");      //用户系统语言
    5.   ……

这样,便能输出相应的用户客户端信息。

6 单击“GET”按钮后,页面将显示“TestGetValue”,如图3.11所示。

图3.11 使用GET方式向页面提交数据

3.2.3 利用Server获取服务器信息

【本节示例参考:\示例代码\C03\ Example_Server】

在开发ASP.NET应用时,需要对服务器进行必要的设置,如服务器编码方式等;或者获取服务器的某些信息,如服务器计算机名、页面超时时间等。这可以通过Server对象来实现。Server对象是HttpServerUtility类的实例,其常用属性和方法如图3.12所示。

图3.12 Server对象常用成员

Server对象常用成员简单介绍,如表3.5所示。

表3.5 Server对象常用成员简单介绍

下面的示例中将使用Server对象的UrlEncode/UrlDecode方法,对一个网络地址URL进行编码和解码。

1 新建一个ASP.NET应用程序,在页面Default.aspx中添加一个文本框控件和一个按钮控件,如图3.13所示。

图3.13 Server对象示例页面控件

2 双击“Button”按钮,在自动生成的单击事件中,添加代码如下:

    string strName=TextBox1.Text;
    Response.Redirect("Default.aspx?name="+strName);

代码使用Response对象的Redirect方法实现页面跳转,目标页面为“P1.aspx”,并使用GET方式提交了一个数据“name”,其值为文本框的输入。

3 双击“Default.aspx”页面,在自动生成的页面加载事件中输入代码:

    Response.Write(Request.QueryString["name"]);

这句代码使用Request对象的QueryString属性,在页面上输出所提交的用户信息。

4 启动程序,将出现页面Default.aspx,在文本框中输入数据并单击“Button”按钮后,页面上将出现相应的输出,如图3.14所示。

图3.14 在页面输出GET数据

5 如果在文本框中输入“wang&zhang”时,示例将产生错误,只输出了“wang”而没有“zhang”,如图3.15所示。

图3.15 提交“wang&zhang”时出现错误

这是因为,符号“&”本身是GET方式传递信息中的特殊符号,用于连接多个传递的值,“name=wang&zhang”将被理解为“name=wang & zhang=''”,所传递的值变为了两个,第一个为“wang”,而第二个为空。要解决这个错误,就需要使用Server对象的UrlEncode方法,来对URL进行编码,以便于在网络上传递。

6 将“Button”单击事件中的代码改为如下:

    string strName=Server.UrlEncode(TextBox1.Text);
    Response.Redirect("Default.aspx?name="+strName);

这时,strName不再是普通字符串形式的URL,而是进行了特殊的编码,以避免类似于(5)中出现的歧义。相应地,再将页面加载事件中的代码改为如下:

    Response.Write(Server.UrlDecode(Request.QueryString["name"]));

Server对象的UrlDecode方法将反过来把编码后的URL解码为普通的字符串。这样再重新编译运行程序,就不会出现(5)中的错误了,如图3.16所示。

图3.16 使用Server.UrlEncode方法对URL进行编码

除UrlEncode/UrlDecode之外,Server还可以使用HtmlEncode/HtmlDecode对HTML文本进行编码/解码操作,此处不再一一赘述。

3.3 共享数据

用户在使用ASP.NET开发Web系统时,会在多个页面间浏览,可能需要共享某些数据,如用户登录信息、数据库连接字符串等。浏览器是没有办法存储数据的,因此需要使用某些特殊对象来实现系统的数据共享。总的来说,包括两个对象:

(1)Application对象:实现程序级别的数据共享;

(2)Session对象:实现会话级别的数据共享。

3.3.1 利用Application共享数据

【本节示例参考:\示例代码\C03\ Example_Application】

当需要在整个程序的级别共享信息时,可以使用Application对象。例如,需要设置一个计数器来统计访问系统的所有人数;或者在程序开始和结束时记录时间,以计算系统的运行时间,这些都可以使用Application对象来实现。

Application对象是HttpApplicationState类的实例,它的生命周期起始于系统开始运行时,终止于系统关闭。其常用的属性、方法及事件如图3.17所示。

图3.17 Application对象常用成员

Application对象常用成员简单介绍如表3.6所示。

表3.6 Application对象常用成员简单介绍

在下面的示例中,将创建两个页面,在第1个页面P1.aspx中向Application对象中添加一个数据,然后在第2个页面中将能够访问到这个数据。

1 新建一个ASP.NET应用,将默认页面Default.aspx重命名为P1.aspx,然后通过“解决方案资源管理器”窗口添加一个新的页面P2.aspx。

2 双击P1.aspx,在自动生成的页面加载事件中输入代码:

    1.   Application.Add("key1","value1");
    2.   Response.Redirect(“P2.aspx”);

第1句代码,将在P1页面加载时向Application对象中添加一项数据,其键为“key1”,值为“value1”。第2句代码将页面跳转到P2.aspx上。

3 双击P2.aspx,在自动生成的页面加载事件中输入代码:

    Response.Write(Application.Contents["key1"]);

这句代码使页面P2加载时显示Applicaion对象内部系统级别的共享数据,这通过其Contents属性数组来获取。

4 启动程序,显示页面如图3.18所示。

图3.18 使用Application获取程序级别共享数据

这时,如果在另外一个客户端的浏览器中输入P2.aspx地址,则同样会显示“value1”,即对于所有的用户,都可以获取Application中的数据。这与下面介绍的Session对象不同。

3.3.2 使用Global.asax文件

【本节示例参考:\示例代码\C03\Example_Global】

在上一节中,介绍了使用Application对象在系统级别共享数据。Global.asax文件与Application对象具有紧密的联系,它的主要功能是:设置一些在程序级别使用的变量及实现Application对象的OnStart和OnEnd等事件。

向工程中添加Global.asax文件的步骤为:右击“解决方案资源管理器”中的工程,弹出快捷菜单,选择“添加新项”命令,在弹出的对话框中选择“全局应用程序类”图标,然后单击“添加”按钮即可,如图3.19所示。

图3.19 添加Global.asax文件

在Global.asax文件中,可以实现Application的OnStart和OnEnd事件。下面的示例中,在Application Start和Application End事件中对其赋值。

代码3-3 添加Application数据:Global.asax

    1.   void Application_Start(object sender,EventArgs e)
    2.   {
    3.      // 在应用程序启动时运行的代码
    4.      Application.Add("StartTime",System.DateTime.Now.ToString());
    5.   }
    6.
    7.   void Application_End(object sender,EventArgs e)
    8.   {
    9.      //  在应用程序关闭时运行的代码
    10.     Application.Add("EndTime",System.DateTime.Now.ToString());
    11.
    12.  }

这样,不管在任何页面中,都可以使用Application中的BeginTime值,通过在Default.aspx的加载事件中添加下面的代码,可以输出系统开始运行的时间。

    Response.Write(Application.Contents["StartTime"]);

运行结果如图3.20所示。

图3.20 使用Global.asax实现全局变量

用这种方法就可以将系统级别的数据共享。通常可以把数据库连接字符串、系统配置参数等信息放在Application对象中。

3.3.3 利用Session共享数据

【本节示例参考:\示例代码\C03\ Example_Session】

上面介绍的Application对象实现了程序级别的数据共享,对于多用户使用的系统来说,有时候需要更细致的数据共享机制:每个用户都可以共享自己的所有数据,而其他用户则无法共享。要实现这种会话级别的共享,需要使用Session对象。

说明

Session意为“会话”,指从用户进入系统到关闭浏览器离开系统的这段交往时间。对于该用户来说,在Session中注册的变量可以保留其值,并可在各个页面中使用。由于这种特点,Session常用于用户在页面之间参数传递、用户身份认证、记录程序状态等。

Session对象是HttpSessionState类的实例,其常用的属性、方法及事件如图3.21所示。

图3.21 Session对象常用成员

Session对象常用成员简单介绍,如表3.7所示。

表3.7 session对象常用成员简单介绍

本节的实例和Application示例类似,它包含两个页面,在第1个页面P1.aspx中向Session对象中添加一个数据,然后在第2个页面中将能够访问到该数据。

1 新建一个ASP.NET应用,将默认页面Default.aspx重命名为P1.aspx,然后通过“解决方案资源管理器”窗口添加一个新的页面P2.aspx。

2 双击P1.aspx,在自动生成的页面加载事件中输入代码:

    1.   Session.Add("key1","value1");
    2.   Response.Redirect("P2.aspx");

第1句代码,将在P1页面加载时向Session对象中添加一项数据,其键为“key1”,值为“value1”。第2句代码将页面跳转到P2.aspx上。

3 双击P2.aspx,在自动生成的页面加载事件中输入代码:

    Response.Write(Session.Contents["key1"]);

这句代码使得页面P2加载时显示Session对象内部系统级别的共享数据,这通过其Contents属性数组来获取。

4 启动程序,显示页面如图3.22所示。

图3.22 使用Session获取会话级别共享数据

与Application不同的是,如果在另外一个客户端的浏览器中输入P2.aspx地址,则不会显示“value1”,这是因为系统认为另一个客户端为其他用户,而Session只支持用户内部的数据共享。

3.3.4 利用Session验证用户

【本节示例参考:\示例代码\C03\Validate_User】

在Web系统中,必须保证用户不能通过直接在浏览器中输入URL直接进入,而必须要先登录才能访问到网页,这时就需要在每个网页中进行身份验证。下面的示例使用【2.3.2】节介绍的Session来完成这个功能。

1 新建一个ASP.NET应用程序,包含两个页面P1.aspx和P2.aspx,并设置P1为起始页。在P1.aspx上添加两个文本框和一个按钮,如图3.23所示。

图3.23 用户登录页面控件

2 双击“登录”按钮,在自动生成的单击事件中添加如下代码。

代码3-4 “登录”按钮单击事件:Default.cs

    1.   ///<summary>
    2.   /// 登录按钮单击事件
    3.   ///</summary>
    4.   protected void Button1_Click(object sender,EventArgs e)
    5.   {
    6.      //从页面上获取用户输入
    7.      string strUserName=this.TextBoxName.Text;
    8.      string strUserPwd=this.TextBoxPwd.Text;
    9.
    10.     //判断用户是否合法,如果合法,写入Session中
    11.     if(IsValide(strUserName,strUserPwd)==true)
    12.     {
    13.         Session.Add("user",strUserName);
    14.
    15.         //跳转到P2.aspx
    16.         Response.Redirect("P2.aspx");
    17.     }
    18.  }

代码首先利用TextBox控件的Text属性获取了用户的输入;然后在第11行调用了一个方法IsValid()。这个方法的输入为用户输入的姓名和密码,通常需要通过查询数据库中是否存在匹配的记录来判定用户是否合法。此处对其不予实现,只简单地用返回值为true来模拟。

代码3-5 判定用户是否合法:Default.cs

    1.   ///<summary>
    2.   /// 判定用户是否合法
    3.   ///</summary>
    4.   ///<param name="_strUserName">用户名</param>
    5.   ///<param name="_strUserPwd">密码</param>
    6.   ///<returns>如果数据库中含有该用户:返回true;否则:返回false</returns>
    7.   private bool IsValide(string_strUserName,string_strUserPwd)
    8.   {
    9.      //查询数据库,此处暂不作实现
    10.     //...
    11.     return true;
    12.  }

最后,页面将跳转到P2.aspx。

3 双击P2.aspx页面,在自动生成的页面加载事件中添加如下代码:

    1.   // 判断用户信息是否存储在Session中,如果没有,返回P1.aspx
    2.   if(Session.Contents["user"]==null)
    3.   {
    4.       Response.Redirect("P1.aspx");
    5.   }
    6.   Response.Write("欢迎进入系统!");

通过判断Session对象中是否含有“user”值,来判断访问P2.aspx页面的用户是否是已经登录的合法用户。如果不是,则将页面跳转到P1.aspx;否则,输出一行欢迎文字。

4 启动程序,出现页面P1.aspx,随意输入用户名和密码,然后单击“登录”按钮,将进入P2.aspx,如图3.24和图3.25所示。

图3.24 通过P1.aspx正常登录

图3.25 成功进入系统

5 重新打开一个浏览器,然后直接在浏览器地址栏中输入P2.aspx的地址,以试图进入系统,此时系统会自动跳转到登录页面P1.aspx。

这样,通过在每一个页面上增加验证Session对象的代码,就可以保证系统只能从登录页面进入,而无法通过其他方式访问。

承上启下

■ 学完本章后,读者需要回答:

1.ASPX页面继承于哪个类?

2.如何使用Response对象向浏览器输出字符串?

3.如何使用Request对象接受用户的POST方式和GET方式提交的数据?

4.如何使用Server对象获取服务器的信息?实现URL字符串、HTML字符串的编码和解码?

5.如何使用Application对象实现程序级别的数据共享?

6.如何使用Session对象实现会话级别的数据共享?

■ 在下一章中,读者将会了解:

1.使用String对象实现字符串的比较,判断是否以特定子串开头、结尾,判断是否包含特定子串,定位,格式化,连接,分裂,插入|填充,删除|剪切,复制,替换和大小写转换。

2.使用StringBuilder对象创建动态字符串,并完成字符串的追加、插入、删除和替换操作。

3.了解正则表达式的概念,掌握.NET中构造正则表达式的技术,并使用Regex类进行字符串模式匹配。

4.了解字符的编码标准,掌握利用System.Text控件对字符编码的转换操作。