第一部份:传统的ASP技术
一、ASP响应用户请求
传统的ASP页面一般是在用户请求某个页面的时候,通过程序向用户返回一些HTML内容。例如:
Exam-001.asp
<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%> <% Response.Write("这是<b>ASP</b>页面返回的信息!现在服务器的时间是:"&Now()&"<br>") %> 这是<b>HTML</b>的信息! |
当用户请求Exam_001.asp后,得到的HTML内容为:
这是<b>ASP</b>页面返回的信息!现在服务器的时间是:2005-2-6 23:33:34<br> 这是<b>HTML</b>的信息! |
这是最简单的方法,就是当用户请求一个页面的时候,就用这个页面来完成某个事情,然后把事情的处理结果告诉请求者。而本例子则是把请求时的服务器时间返回给请求者。于是在传统的ASP网站中,往往就是一个ASP文件完成一件事情。这样一来感觉上事情清晰明了。如我们常常可以看到一些网站的ASP程序如下:reg.asp,edit_data.asp,save_data.asp,delete_data.asp等。明显的可能就是一个用户注册,资料编辑,资料保存和一个资料删除程序。当然,如果一个网站功能不是很多,像这样的完成一些事情也还过得去。但如果事务多起来的时候,就明显的ASP文件会很多。但每一个文件可能只有几K到几十K,因为根据事情来决定ASP程序的长度!
一般有三种方法来请求一个页面。一是直接输入这个文件的名,如:http://server_name/exam_001.asp 第二种方法就是通过链接到这个文件,其实这与直接输入文件名的效果是一样的!但我们可以在链接后加一些参数(在后面将详细说明如何取得用户参数)。第三种方法是通过HTML的form标签的action属性指定到这个文件,同时也可以传递一些参数。其中我们对第三种情况举一个例子:
Exam-002.asp
<form name="form1" method="post" action="exam-001.asp"> 点击到exam-001.asp <input type="submit" name="Submit" value="点击"> </form> |
当用户点击“点击”按钮的时候就会请求到Exam-001.asp文件。最后会得到Exam-001.asp文件所返回的信息。我们可以在同一个form内添加多个submit按钮,但不管点击哪个,都将会返回form中action所指示的页面内容。但这为我们打开了一个思路,我们可不可以用同一个form来得到不同的页面呢?显然是可以的,而我们一般采用的是DHTML方法,也就是动态的改变form的action内容。例:
Exam-003.asp
<form name="form1" method="post" action=""> This page exam-003.asp<br> <input type="submit" name="Submit2" value="exam-001.asp" onClick="change_action('exam-001.asp')"> <input type="submit" name="Submit3" value="exam-002.asp" onClick="change_action('exam-002.asp')"> <input type="submit" name="Submit" value="This page" onClick="change_action('exam-003.asp')"> </form> <script language="JavaScript"> <!-- function change_action(m_actions){ // alert(m_actions); form1.action=m_actions; } --> </script> |
这样,当我们点击不同的按钮的时候,就可以到不同的页面上去了!而这每个按钮都是submit的属性。同是要说一下的是,如果form的action属性没有赋值的时候就会是向当前页面发送请求,同时也会返回当前页面的内容。
ASP.net的读者注意了:很多ASP.net的读者不明白,为什么ASP.net页面里经常会有很多的submit按钮,它们不会混淆吗?看了这个例子就应该明白,只要我们自己控制好每个submit的属性,它们是不会混淆的。而好在ASP.net里不用我们自己去管理这些submit是怎样协调工作的,我们只用知道,一个form里是可以有多个submit的,而且每个submit的事情也是可以不一样的。 |
二、取得用户参数
ASP的成功之处就是可以方便快捷的与用户进行交互!我们一般用以下几种方法取得用户提供给程序的一些参数。一是通过在文件请求的后面加上变量名和参数,如:http://setver_name/exam-004.asp?m_name=张三&m_age=19 这样用户就将两个变量m_name和m_age以get方法传递给了程序exam-004.asp。但程序用不用还是另外一回事,一般我们采用Request.QueryString()来取得变量!例如:
Exam-004.asp
<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%> <% s_name =Request.QueryString("m_name") s_age =Request.QueryString("m_age") Response.Write("<font color=red>"&s_name&"</font>("&s_age&"岁)您好!") %> |
用http://server_name/exam-004.asp?m_name=张三&m_age=25来请求页面的时候可以得到以下HTML内容:
<font color=red>张三</font>(25岁)您好! |
第二种方法是通过form来传递参数!我们用Request.Form()来取得变量。例如:
exam-005.asp
<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%> <% s_name =Request.Form("m_name") s_age =Request.Form("m_age") Response.Write("<font color=red>"&s_name&"</font>("&s_age&"岁)您好!<br>") %> <form name="form1" method="post" action=""> 姓名: <input name="m_name" type="text" id="m_name" size="10"> 年龄: <input name="m_age" type="text" size="10"> <input type="submit" name="Submit" value="提交"> </form> |
这个例子用自己来处理用户提交的参数!一般用form传递数据的方法都是post。
POST与GET的区别:很多人不明白,这两种参数传递到底有什么区别。GET方法一般传递的数据较少!变量名及一些值会在请求文件的后面跟出来。其实就是第一种方法传递参数。而POST则传递的数据内容多一些,而且不会在文件名后面跟出来。所以GET不能用Request.Form()来取得参数。应该用什么?读者可以自己想想。那么POST方法是不是比GET方法安全一些呢?因为它的变量及值不给在文件名后面跟出来。其实不然,POST和GET方法的安全性几乎是一样的,只是POST一般看不见而已。是采用POST还是GET,根据需要来决定。另外GET方法一般在ISAPI中用的很多,也就是一些服务器的底层服务。如一些搜索引擎,都是用的GET方法。 |
在HTMLL里有一个看不见的标签,就是type属性为hidden的input标签。这个标签在传递一些非常变量的时候很有用,可以用它在好几个页面中传递数据。虽然可以用cookie及Session来保存一些用户信息,但在单个页面里保存一些信息的时候,这个方法还是很好用的!后面我们将用到它的一些有意思的用法。最后要说明一下的是,在ASP.net中,与用户交流取得用户变量的方法也是采用这样的传统方法。还有一个问题就是很多人不明白怎样与客户端JavaScript脚本的变量进行交互。其实理解JavaScript的工作原理就行了!
与JavaScript脚本进行变量交互。看这样的一个例子:
Exam-006.asp
<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%> <form name="form1" method="post" action=""> <input name="m_name" type="text" id="m_name" size="20"> <input type="submit" name="Submit" value="提交"> <input type="button" name="Submit2" value="JavaScript" onClick="m_alert()"> </form> <% s_name=Request.Form("m_name") Response.Write("<script language='JavaScript'>"&chr(13)) Response.Write("<!--"&chr(13)) Response.Write("function m_alert(){"&chr(13)) Response.Write(" alert('"&s_name&"您好!"&"');"&chr(13)) Response.Write("}"&chr(13)) Response.Write("-->"&chr(13)) Response.Write("</script>"&chr(13)) %> |
当我们输入“张三”提交后可以得到这样的HTML代码:
<form name="form1" method="post" action=""> <input name="m_name" type="text" id="m_name" size="20"> <input type="submit" name="Submit" value="提交"> <input type="button" name="Submit2" value="JavaScript" onClick="m_alert()"> </form> <script language='JavaScript'> <!-- function m_alert(){ alert('张三您好!'); } --> </script> |
其实也就是用ASP生成JavaScript代码。因为ASP是在服务器上运行的,它的任务就是处理一些事务,然后以文本的形式向客户端返回一些信息。而ASP所返回的信息再由客户端的浏览器来解释。所以可以很简单的把ASP的变量s_name的值赋给JavaScript里去。当然JavaScript是不能共用一个变量的,因为它们运行的地方都不一样,怎么可以共用变量呢?但如果可以把值传过来的话,就已经可以解决所有的事务了!
那么反过来,JavaScript怎样向ASP传递变量呢?其实这个在exam-003.asp里已经完成了!读者可以自己分析一下,更复杂的变量传递应该怎样做!
注意:JavaScript是与用户交互的一个重要手段,在ASP.net仍然保留了这一做法。但并不是所有的浏览器都支持JavaScript,所以我们要注意,使用JavaScript时,不要太相信你的所有JavaScript语句都会被执行。好在ASP.net里可以自动生成JavaScript,而且可以根据不同的浏览器生成它可以支持的代码。这为我们省去了不少的麻烦! |
三、返回处理信息
ASP的信息返回基本上就是用Response.Write()来返回一些文本信息。当然也可以用一些组件将信息写入数据库及文件。再就是再HTML中直接的插入一些ASP变量的值,如:<%=s_name%> 就会在HTML中插入s_name这个变量的值。
显然这些信息返回的方法是有限的。特别是当一个HTML页面的内容比较多的时候,还用这些方法,就会出现反应时间长,或者HTML页面与ASP代码混乱的局面。这里我就不举例了,在讨论传统的ASP方法的最后,我会给出一个服务器文件操作及管理的例子。可以看到,它的ASP代码与HTML几乎是不能分开的。因此在ASP.net中,一方面仍然保留了这两种信息返回的方法,同时还添加了很多其它的方法。特别是面向对象的程序设计思维的改变,它的信息返回方式可以说是千变万化了!
四、与服务器上COM组件一同工作
ASP的功能是十分的有限的,但它与COM一起工作时,威力可以说是成百上千倍的增加了!
其实COM组件就是一个应用程序,也就是二进制文件。它与一般的EXE程序不同之处就是它不能独立的运行,必须在一个容器内运行(所以它的扩展名是DLL)。而我们ASP的运行环境就是一个COM容器。所以它可以加载COM组件。COM组件具体的做什么事,完全该写这个COM组件的程序员来决定。因此我们一般都只能使用这些组件,也就是这些组件提供给我们的一些方法或接口。而一个相对麻烦的问题就是,这个DLL文件不能在运行时加载,只能是事先在服务器上注册过的。如果我们不能操作服务器的话,那么这个COM组件我们就用不成了!当然,由于ASP的发展确实很快,目前国内很多ASP服务器提供商都安装了一些常用的组件,如JMail,FSO,OLEDB等。
由于COM组件的特殊性,很多人都想知道COM组件里到底是什么?为什么在ASP里可以很轻松的引用它?而在ASP.net中为什么又没有用COM组件了呢?
ASP.net读者注意:在ASP.net已经不能用COM组件了,但为了使程序开发出来的一些很好用的组件不至于浪费,在ASP.net中增加了一个RCW(Runtime Callable Wrapper),位于代码和COM组件之间的特殊的.net代理类。由于.net类的托管,使得程序必须依赖于.net类库才能运行,而COM组件不是托管的,所以不能在.net环境中使用。因此用RCW进行一个过度。 |
其实COM组件的神秘之处就是它的封装性,使得一般人很难看到COM内部是如何工作的。因此很多人在写ASP程序之后,都会想给程序加密。为什么会想这样呢?无非不想让自己的心血白白的浪费。而所有的加密系统都是可以解密的,因此没什么特别的了!于是在ASP.net中,直接给源程序进行编译,使之成为二进制文件!于是有人不理解,为什么可以直接请求服务器里的二进制文件。其实也没什么,如果写过CGI程序或是ISAPI程序就会知道,其实我们在请求服务的时候,服务器先执行的还是一些二进制的文件。如:当我们请求ASP文件的时候,服务器会让ASP文件映射到asp.dll这个二进制文件上,然后对ASP文件进行解释执行,最后返回结果。如果我们把其它文件(如HTML文件)也映射到asp.dll上,那么其它文件里也可以写入ASP代码。而这些工作都是由服务器自己完成的。那么ASP.net的运行环境可以说是开放式的,我们不但可以自己定义一些映射关系,还可以自己写一些过滤器,使得在返回用户信息之前先对用户的一些信息进行处理(如网站文件访问统计)。
既然是让我们用户自己来处理一些底层的事情,那自然也得让我们可以自己写二进制文件了。所以很自然的,我们在ASP.net里,可以自己写一些DLL文件。而这些文件则是由服务器自己加载的!注意:ASP.net的访问目录必须是一个应用程序,否则不能执行ASP.net的程序。
ASP.net中虽然不能用COM组件,但它的另一个功能很强大。那就是用户自定义组件的使用。这与传统的COM组件有些类似,也是提供一些方法和接口供用户使用,而且也是经过编译的。它不用注册,可以直接被ASP.net运行环境所加载。因此这一功能远远的超过了传统的COM组件。可惜目前还没有太多的第三方组件可用,至少不象COM那样的多。因此ASP.net中也自带了一些COM组件(我是这样认为的,因为确实ASP.net里的有些类是以前的COM组件,所以我称为这些是ASP.net自带的COM组件)。但请注意,这些自定义的组件与传统的COM组件是有本质的区别的!
五、一个传统的ASP例子
最后给出一个ASP实用的例子,源代码较长,这里只给出大概的工作原理,源程序可以在我的网站上下载。给出这个例子的目的是让大家思考一下,对于一个中大型的网站系统,一般都要在一个ASP文件里完成多个功能,以便来减少服务器上的文件数目,也便于管理。试想,一个网站文件管理系统一般会有多少个文件呢?我们可以充分发挥ASP的潜能,让它在一个文件里完成文件(夹)显示,复制,删除,文本文件的编辑等各种工作。
Exam-007.asp(一个网站文件管理系统)
当第一次请求这个文件时,列出所在的目录里的所有文件及文件夹,并提供对文本文件的修改按钮,对其它文件(夹)提供复制和删除的按钮,还提供在当前目录创建文件及文件夹的按钮。全部用JavaScript来响应这些事件。大概的源文件: base_path =Request.ServerVariables("APPL_PHYSICAL_PATH") '网站物理路径 base_path =Lcase(base_path) URL =Request.ServerVariables("HTTP_HOST") URL ="http://"&URL&"/" base_file =Request.ServerVariables("PATH_TRANSLATED") '文件物理路径 current_path =Request.Form("m_current_path") '当前目录 if current_path="" then current_path=base_path end if if right(current_path,1)<>"/" then current_path=current_path&"/" end if m_type =Request.Form("m_type") '当前操作,由JavaScript响应用户操作来动态赋值 <% if m_type="" or m_type="list_file" then%> 在这里列出当前目录的所以文件及文件夹!并提供一些相关的操作。 <%end if%> <%if m_type="其它操作"%> 在这里执行一些其它的操作 <%end if%> |
一些相关的JavaScript函数: <script language="javascript"> <!-- function create_obj(m_file){//用于响应创建文件或文件夹的事件 if(form1.m_obj_name.value==""){ ‘对象名为空时…… } if(confirm("创建"+form1.m_obj_name.value+"吗?")){ ‘确认创建文件或文件夹 } } function delete_file(m_obj){ if(confirm("删除文件"+m_obj+"吗?")){ ‘确认删除文件 } } function edit_file(m_file){ if(confirm("编辑文件"+m_file+"吗?")){ ‘确认编辑文件 } } function delete_folder(m_folder){ if(confirm("删除文件夹"+m_folder+"吗?")){ ‘确认删除文件夹 } } 完整代码请从网上下载! |
一些相关ASP代码: if m_type="delete_folder" then m_delete_folder =Request.Form("m_delete_obj") Set fs = CreateObject("Scripting.FileSystemObject") if fs.FolderExists(m_delete_folder) then fs.DeleteFolder m_delete_folder,true msg_box_f("文件夹已经删除!请返回后刷新!") else msg_box_f("目标文件夹不存在,无法删除!") end if set fs=nothing end if if m_type="create_obj" then '新建文件 m_delete_file=Request.Form("m_delete_obj") Set fs = CreateObject("Scripting.FileSystemObject") if Request.Form("m_obj_type")="0" then Set a = fs.CreateTextFile(m_delete_file, True) a.Close() set a=nothing set fs=nothing msg_box_f("对象已经创建!请返回后刷新!") end if if Request.Form("m_obj_type")="1" then fs.CreateFolder(m_delete_file) set fs=nothing msg_box_f("对象已经创建!请返回后刷新!") end if end if if m_type="save_file" then m_delete_file=Request.Form("m_delete_obj") m_file_resume=Request.Form("m_file_resume") Set fs = CreateObject("Scripting.FileSystemObject") Set a = fs.CreateTextFile(m_delete_file, True) a.write(m_file_resume) a.Close() set a=nothing set fs=nothing msg_box_f("文件已保存!请返回后刷新!") end if '复制文件 if m_type="copy_file" then m_old_name=Request.Form("m_delete_obj") m_new_name=Request.Form("m_id") 'response.write(m_old_name&"->"&m_new_name) 'response.end() Set fs = CreateObject("Scripting.FileSystemObject") if fs.FileExists(m_old_name) then if fs.FileExists(m_new_name) then msg_box_f("目标文件已经存在!复制错误!") else fs.CopyFile m_old_name,m_new_name,false msg_box_f("文件名复制成功!请返回后刷新!") end if else msg_box_f("源文件不存在无法复制!") end if set fs=nothing end if |
运行时的一些图片: |
好了,这个例子就只说这么多,完整的代码读者可以从网上下载。要说明的是,在一个ASP文件里是可以完成很多工作的,而唯一的缺点就是文件太大,不好管理。而ASP.net程序就不一样了,虽然也是在一个文件里,但工作原理就大不相同了。显然我们在ASP.net出现以前就想过要这么做,而且看的出来,这样做让我们付出了很多的心血来写一些基础的程序代码。可以看的出来ASP.net就是应这样的要求而产生的。
文章来源:http://computer.mblogger.cn/wucountry/posts/28279.aspx