Asp.net夜话之二: asp.net内置对象  

Author: 周金桥

Date: 2008-09-15

在今天我主要要介绍的有如下知识点:
Request
Response
Server
Session
Cookie
Application
<%%> 及<%=%> 表达式

准确地说,asp.net 并没有内置对象这一说,jsp 里确实把request 、response 这些当作jsp 的内置对象,这里只不过是借用了一下jsp 的说法而已。上面提到的很多都是在做asp.net 开发时无需new 就能使用的对象(类似的还有很多,在asp.net 中所有的网页都是继承自System.Web.UI.Page 这个类,上面的提到多是Page 类的属性)。

在Web 中处于中心的是Web 服务器,用来处理客户端的HTTP 请求。由于HTTP 是一种无状态的协议,也就是它并不记得上一次谁请求过它,不会主动去询问客户端,只有当客户端主动请求之后,服务器才会响应。

Request
Request 封装了客户端请求信息。Request 的常见属性如下:

属性名

值类型

说明

ApplicationPath

String

获取请求的资源在网站上的根路径

ContentEncoding

Encoding

设置请求对象的编码

Cookies

HttpCookieCollection

客户端发送到服务器的Cookie 集合

QueryString

NameValueCollection

当前请求的查询字符串集合

UrlReferrer

Uri

获取用户由哪个url 跳转到当前页面

Response
Response 代表了服务器响应对象。每次客户端发出一个请求的时候,服务器就会用一个响应对象来处理这个请求,处理完这个请求之后,服务器就会销毁这个相应对象,以便继续接受其它客服端请求。
Response 常用属性如下:

属性名

值类型

说明

Charset

string

表示输出流的所使用的字符集

ContentEncoding

Encoding

设置输出流的编码

ContentLength

Int

输出流的字节大小

ContentType

string

输出流的HTTP MIME 类型

Cookies

HttpCookieCollection

服务器发送到客户端的Cookie 集合

Output

TextWriter

服务器响应对象的字符输出流

RedirectLocation

string

将当前请求重定向

Response 常用方法

属性名

返回值类型

说明

AppendCookie

void

向响应对象的Cookie 集合中增加一个Cookie

Clear

void

清空缓冲区中的所有内容输出

Close

void

关闭当前服务器到客户端的连接

End

void

终止响应,并且将缓冲区中的输出发送到客户端

Redirect

void

重定向当前请求

下面具体说明,用Dreamweaver8 创建一个aspx 页面,代码如下:

1.  <%@ Page Language="C#" ContentType="text/html" ResponseEncoding="gb2312" %> 
2.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
3.  <html xmlns="http://www.w3.org/1999/xhtml"> 
4.  <head> 
5.  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
6.  <title>Request例子</title> 
7.  </head> 
8.  <body> 
9.  <table border="1" width="600px" bordercolordark="#2B72A2" bordercolorlight="#993333"> 
10. <tr><td colspan="2" bgcolor="#80ffff">Request</td></tr> 
11. <tr><td>ApplicationPath(网站路径)</td><td><%=Request.ApplicationPath%></td></tr> 
12. <tr><td>ContentEncoding(网页编码)</td><td><%=Request.ContentEncoding%></td></tr> 
13. <tr><td>Cookies个数</td><td><%=Request.Cookies.Count%></td></tr> 
14. <tr><td>QueryString个数</td><td><%=Request.QueryString.Count%></td></tr> 
15. <tr><td>UrlReferrer(上一请求页面)</td><td> <%=Request.UrlReferrer%></td></tr> 
16. <tr><td colspan="2" bgcolor="#80ffff">Response</td></tr> 
17. <tr><td>Charset</td><td><%=Response.Charset%></td></tr> 
18. <tr><td>ContentEncoding(网页编码)</td><td><%=Response.ContentEncoding%></td></tr> 
19. <tr><td>Cookies个数</td><td><%=Response.Cookies.Count%></td></tr> 
20. <tr><td>ContentType</td><td><%=Response.ContentType%></td></tr> 
21. </table> 
22. </body> 
23. </html>

将新建的页面保存为RequestAndResponse.aspx 并保存到C:\Inetpub\wwwroot 下,然后打开浏览器在地址栏中输入:https://localhost/RequestAndResponse.aspx ,实际上url 地址不区分大小写,以上地址全部小写也没有关系,运行结果如下:

从上面的结果我们可以看出利用Dreamweaver 创建的网页,如果采用默认编码,请求对象的字符编码是UTF-8 ,而响应对象的编码为gb2312 。这样极有可能可能产生乱码问题。所谓乱码,就是用一种编码的字符串却用了另一种编码来显示,造成不能正常显示的现象。就像我用普通话说“ 请给我来一杯茶“ ,结果是一个只懂德育的人听了,他自然听不懂我说什么,不能正常交流。另外,需要说明的是常见的服务器响应的ContentType 是“text/html” ,代表响应是以HTML 文件形式传输的。还有一些其它形式的ContentType ,如下:
image/jpeg :响应对象是jpeg 图片
text/xml :响应对象是xml 文件
text/javascript :响应对象是javascript 脚本文件
Response 的ContentType 属性默认是“text/html” ,表示服务器以HTML 文件响应客户端请求,如果需要用其它方式响应客户端请求,则需要设置ContentType 属性。假如我们需要用jpeg 图片的格式响应客户端请求,则需要设置ContentType 属性为“image/jpeg” ,然后将图片内容输出到客户端,这样客户端就会看到jpeg 格式的图片而不是HTML 文件。

Server
Server 对象是用于获取服务器的相关信息的对象。它常用方法如下:

属性名

返回值类型

说明

Execute

void

执行指定的资源,并且在执行完之后再执行本页的代码

HtmlDecode

string

消除对特殊字符串编码的影响

HtmlEncode

string

对特殊字符串进行编码

MapPath

string

获取指定相对路径在服务器上的无力路径

Transfer

void

停止执行当前程序,执行指定的资源

UrlDecode

string

对路径字符串进行解码

UrlEncode

string

对路径字符串进行编码

上面的方法光从概念上来说,似乎还是让人不能分清他们到底有什么作用,特别Excure/ Transfer 、HtmlEncode (HtmlDecode )/ UrlEncode (UrlDecode)这两组。在讲述他们分别之前先讲述MapPath 这个方法的作用,在我们上传文件的时候要以物理路径保存上传文件到服务器,而我们使用得最多的是相对URL 地址,这个方法就起到了将相对URL 地址转换成服务器物理路径的作用。
为了说明Excure/ Transfer 及HtmlEncode (HtmlDecode)/ UrlEncode (UrlDecode)的区别,我们还是用实例代码来展示,用Dreamweaver8 创建一个aspx 页面,代码如下:

1.  <%@ Page Language="C#" ContentType="text/html" ResponseEncoding="gb2312" %> 
2.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
3.  <html xmlns="http://www.w3.org/1999/xhtml"> 
4.  <head> 
5.  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
6.  <title>Server对象的常见方法实例</title> 
7.  </head> 
8.  <body> 
9.  <ul> 
10. <li>Server.MapPath(".")=<%=Server.MapPath(".")%></li> 
11. <li><%=Server.HtmlEncode("<h1>Asp.net夜话之二:asp.net内置对象</h1>")%></li> 
12. <li><h1>Asp.net夜话之二:asp.net内置对象</h1></li> 
13. <li><%=Server.UrlEncode("<a href=\"http://blog.csdn.net/zhoufoxcn\">周公的专栏</a>")%></li> 
14. <li><a href="http://blog.csdn.net/zhoufoxcn">周公的专栏</a></li> 
15. </ul> 
16. </body> 
17. </html>

将新建的页面保存为ServerDemo.aspx 并保存到C:\Inetpub\wwwroot 下,然后打开浏览器在地址栏中输入:https://localhost/Request/serverdemo.aspx ,运行结果如下:
 
从Server.MathPath(“.”) 输出“C:\Inetpub\wwwroot” ,证明确实能获取到相对路径的在服务器上的实际物理地址。
在上面的例子中我们想在网页中输出HTML 代码,如果直接输出往往得不到想要的效果,这时可以借助HtmlEncode 方法对要输出的HTML 代码进行编码,这样输出到浏览器上的时候就能看到HTML 代码,而不是HTML 形式的效果。HtmlDecode 方法则是用来消除这种影响。
如果我们直接输出“<a href="http://blog.csdn.net/zhoufoxcn"> 周公的专栏</a>” 这个字符串的话,在网页上会显示一个超级链接,但是有时候我们希望把这个超级链接作为QueryString 的一个参数,由于url 地址的特殊性,比如“:” 、“/” 等字符串在URL 地址中有特殊的含义,要想输出这些字符,直接输出是不行的,需要进行某种转换,并且将来还能转换回来。经过UrlEncode 方法转换之后,“:” 、“/” 分别转换成了“%3a” 和“%2f” 这样的字符,并且汉字也进行了转换。UrlDecode 方法则是将“%3a” 和“%2f” 等这样的字符转换成我们原本要表示的字符。

前面我们提到,在HTTP 中,服务器与客户端并不是时时保持连接状态,而是服务器被动地等待客户发送请求,服务器才进行响应。因此,在大部分情况下,服务器并不会管客户端是否还依然存在。
在这种情况下,假如用户通过访问一些需要权限的页面,在他输入正确的用户名和密码之后第一次他访问a 页面,隔几分钟之后再访问同样需要权限才能访问的b 页面,这是他还需要输入用户名和密码吗?按照清理来说如果这个时间间隔比较短,我们不应该要求频繁用户输入这些信息,可是服务器又不记录这些信息,我们有没有办法解决这个问题呢?
答案是有的,就是利用Session 或者Cookie 。

Session
Session 对象用来保存与特定用户相关的信息,Session 中的数据保存在服务器端,在客户端需要的时候创建Session ,在客户端不需要的时候销毁Session ,使它不再占用服务器内存。前面说了服务器并不管客户端是否依然存在,因而它也无法确定客户端什么时间不再使用它,但是如果在客户端不再用的时候不及时销毁Session 的话,服务器很快就会内存不足。为了解决这个问题,给Session 加了一个生命周期,当服务器发现Session 超过了它的生命周期,就会释放该Session 所占用的内存空间。在asp.net 中Session 的默认生命周期是20 分钟,也就是当我们在9:00 的时候设置了一个Session ,如果在9:20 之前客户端没有任何请求,那么它的生命周期就到9:20 分钟结束。但是一旦用户在9:19 又向服务器发送了一个请求,那么这个Session 现在的生命周期就是在当前时间的基础上再加上20 分钟,也就是此时这个Session 的生命周期是到9:39 结束。
Session 具有以下特点:
Session 中的数据保存在服务器端;
Session 中可以保存任意类型的数据;
Session 默认的生命周期是20 分钟,可以手动设置更长或更短的时间。
假设我们要设置一个Session 用来保存用户名,这个Session 的名字是“UserName” ,值是“zhoufoxcn” ,代码如下:

1.    Session[“UserName”]=”zhoufoxcn”;

一个网站里用到Session 的地方肯定不止一个,所以在设置和获取Session 的时候通过Session 的名在来操作,并且Session 被设置成能存储任意类型的对象(即Object 类型),所以获取Session 的时候要根据设置的时候的实际类型进行响应的强制类型转换(当然如果在Session 中存放像int/byte/short 这样的数据类型,获取Session 的值算是一种拆箱操作而不是强制类型转换),对于上面的Session ,获取Session 的值的代码如下:

1. string username=(string)Session[“UserName”];

对于上面的代码,有个问题需要注意:当没有设置相应的Session 或者Session 因为超过生命周期而被销毁时,上面的代码有可能抛出异常。我们可以先判断是否存在指定名称的Session ,如果不存在就不用获取了,仅当存在的情况下才获取Session 的值,上面的代码可以改进如下:

1. string userName; 
2.  if(Session["UserName"]!=null) 
3.  { 
4.  //当指定名称的Session存在时,获取指定Session的值 
5.  userName=(string)Session["UserName"]; 
6.  }

Cookie
Cookie 对象和Session 对象一样也是用来保存特定的用户相关的数据,不过Session 不同的是Cookie 保存在客户端而不是服务器上,每次客户端发出请求的时候都会把Cookie 一起发送到服务器,服务器每次响应客户端请求的时候会重新把Cookie 发送到客户端保存。
Cookie 保存数据有以下特点:
Cookie 中的数据保存在客户端;
Cookie 中只能保存字符串类型的数据,如果需要在Cookie 中保存其它类型数据,需要将其转换成字符串类型后保存;
Cookie 也有其默认生命周期,也可以手动设置,最大可设置成50 年之后过期。
同Session 的情况一样,有可能在一个网站中使用到的Cookie 不止一个,我们仍通过Cookie 的名称来区分不同的Cookie 。
设置Cookie 的过程就是在服务器的响应对象Response 的Cookie 集合中增加一个Cookie 的实际,Response 对象会把这个Cookie 集合中的所有Cookie 都发送客户端。代码如下(仍以保存用户名为例):

1.   HttpCookie cookie = new HttpCookie("UserName", "zhoufoxcn"); 
2.  Response.Cookies.Add(cookie);

  获取Cookie 就是从客户端的请求对象中找到对应名称的Cookie ,当然也有可能出现Cookie 不存在的情况,所以在获取之前也需要检查指定名称的Cookie 是否存在,代码如下:

1.   string userName; 
2.  if (Request.Cookies["UserName"] != null) 
3.  { 
4.       userName = Request.Cookies["UserName"].Value; 
5.  }

细心的朋友可能会留意到前面讲到Session 和Cookie 的时候,我都说他们是针对特定用户保存的数据,也就是那些数据并不是每个人都能用到。Session 和Cookie 一般用来一些针对特定用户的信息,比如用于保存用户名等,因为是针对特定用户的,所以不会针对张三设置用户名保存在Session 或者Cookie 中之后再去或者这个值的时候得到的是李四的用户名。但是在某些情况下,我们又希望保存一些共有信息,这样大家都能设置或者获取,比如自从服务器启动以来某个页面被打开的次数,这时用Session 或者Cookie 就不合适了。这就需要用Application 了。

Application
Application 和Session 存储的数据类型和存储位置一样,都是存放Object 类型的数据(也就是任意类型),并且存放在服务器上,不同的Application 中的数据可以由网站中所有的用户来设置或者获取。并且Application 中存放的数据没有时间限制,除非我们手动删除或者服务器重新启动,否则存放的数据都会丢失。
下面是Session 、Cookie 和Application 的区别:

名称

使用范围

存储位置

存放数据类型

生命周期

Session

特定用户

服务器

Object ,也就是任意类型

有,可以自行设置

Cookie

特定用户

客户端

String ,也就值字符串

可以自行设置

Application

所有用户

服务器

Object ,也就是任意类型

下面我们以一个小例子来说明Session 和Application 的区别。
我们用Dreamweaver8 创建两个页面,分别为SessionTest.aspx 和ApplicationTest.aspx ,保存到C:\Inetpub\wwwroot 目录下,它们的代码都是一样的,如下:

1.   <%@ Page Language="C#" ContentType="text/html" ResponseEncoding="gb2312" %> 
2.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
3.  <html xmlns="http://www.w3.org/1999/xhtml"> 
4.  <head> 
5.  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
6.  <title>Application和Session的例子</title> 
7.  </head> 
8.  <body> 
9.  <% 
10. //如果没有设置名为"ApplicationCount"的Application 
11. int applicationCount=1; 
12. int sessionCount=1; 
13. if(Application["ApplicationCount"]==null) 
14. { 
15. Application["ApplicationCount"]=1; 
16. } 
17. else//否则取出该Session,并且在当前值上加1 
18. { 
19. applicationCount=(int)Application["ApplicationCount"]+1; 
20. Application["ApplicationCount"]=applicationCount; 
21. } 
22. //如果Session["SessionCount"]为空,即没有设置该名字的Session 
23. if(Session["SessionCount"]==null) 
24. { 
25. Session["SessionCount"]=1; 
26. } 
27. else 
28. { 
29. sessionCount=(int)Session["SessionCount"]+1; 
30. Session["SessionCount"]=sessionCount; 
31. } 
32. Response.Write("当前页面由Application记录到的被访问了"+applicationCount+"次<br/>"); 
33. Response.Write("当前页面由Session记录到的被访问了"+sessionCount+"次<br/>"); 
34. %> 
35. </body> 
36. </html>

这时我们在浏览器地址栏里输入:https://localhost/sessiontest.aspx ,会看如下结果Session 和Application 中的值是一样的,即使我们按F5 刷新页面,结果也是一样,如下图:


 
然后我们重新打开一个浏览器应用程序(注意不要在当前窗口中输入),会看到如下情况:
 
为什么特地强调要在新浏览器窗口中打开另一个页面呢?因为有些浏览器会视同为同一个Session ,导致出现不了预期的效果。通过上面的例子证明了Application 确实是属于所有网站用户的,它适合保存全局的数据信息,如网站从Web 服务器启动以来接受的请求个数或者当前在线总人数;而Session 只与特定用户有关,只适合保存特定用户的信息,比如用户的用户名。

<%%> 表达式
<%%> 用来编写程序的代码部分。在其中可以声明变量和方法。如下:

1.    <% 
2.      string name = Request.Form["userName"].Trim(); 
3.      string userName; 
4.      if (Request.Cookies["UserName"] != null) 
5.      { 
6.          userName = Request.Cookies["UserName"].Value; 
7.      } 
8.       %>

在<%%> 就是符合C# 要求的代码。

<%=%> 表达式
<%=%> 是用来向输出流中输出变量的值。其用法如下:
<% int i = 6; %>
<%=i %>

九九乘法表是大家相当熟悉的了,下面我们分别用Response 对象的Write 方法和上面的<%%> 及<%=%> 来输出九九乘法表。如下图
 
用Response 对象输出九九乘法表的代码如下:

1.    <%@ Page Language="C#" ContentType="text/html" ResponseEncoding="gb2312" %> 
2.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
3.  <html xmlns="http://www.w3.org/1999/xhtml"> 
4.  <head> 
5.  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
6.  <title>Server对象的常见方法实例</title> 
7.  </head> 
8.  <body> 
9.  <table border="1" width="600px"> 
10. <tr><th colspan="9">九九乘法表</th></tr> 
11. <% 
12. for(int i=1;i<10;i++) 
13. { 
14. Response.Write("<tr>"); 
15. for(int j=1;j<10;j++)//输出一行中的每列 
16. { 
17. if(j<=i){//如果有内容 
18. Response.Write(String.Format("<td>{0}×{1}={2}</td>",j,i,j*i)); 
19. 
20. } 
21. else{//否则输出空单元格 
22. Response.Write("<td> </td>"); 
23. } 
24. } 
25. Response.Write("</tr>"); 
26. } 
27. %> 
28. </body> 
29. </html>

用<%%> 及<%=%> 输出九九乘法表的代码如下:

1.  <%@ Page Language="C#" ContentType="text/html" ResponseEncoding="gb2312" %> 
2.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
3.  <html xmlns="http://www.w3.org/1999/xhtml"> 
4.  <head> 
5.  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
6.  <title>九九乘法表</title> 
7.  </head> 
8.  <body> 
9.  <table border="1" width="600px"> 
10. <tr><th colspan="9">九九乘法表</th></tr> 
11. <% 
12. for(int i=1;i<10;i++) 
13. { 
14. %> 
15. <tr> 
16. <% 
17. for(int j=1;j<10;j++)//输出一行中的每列 
18. { 
19. if(j<=i){//如果有内容 
20. %> 
21. <td><%=j%>×<%=i%>=<%=i*j%></td> 
22. <% 
23. } 
24. else{//否则输出空单元格 
25. %> 
26. <td> </td> 
27. <%} 
28. } 
29. %> 
30. </tr> 
31. <%} 
32. %> 
33. </body> 
34. </html>

可以看出用Response.Write() 输出和<%=%> 输出最后的效果是一样的。

 

 

 

下一篇:asp.net夜话之三:表单和控件-周金桥