直播中
在ASP 3.0中,緩沖的缺省狀態(tài)是打開的,且沒有輸出被發(fā)送,除非使用Response.Flush指定做這個工作或者頁面已到末端。這意味著創(chuàng)建cookie的代碼可以在頁面上的任何位置,直到任何輸出“刷新”(flush)到客戶端前,它都可以被執(zhí)行。
要讀現(xiàn)有的cookie,使用Request.Cookies集合。可以單獨訪問其中的項目,方法類似于創(chuàng)建它們時使用的方法。
StrSingleValue = Request.Cookies(“item-name”)
StrSubItemValue = Request.Cookies(“item-name”)(“sub-item-name”)
注意Request.Cookies集合(和所有其他Request集合一樣)是只讀的。Response.Cookies集合是只寫的,事實上可以訪問這個集合中一系列cookie的名稱,而不是它們的值。
遍歷Cookies集合
為了使用Cookies集合更加方便,可使用名稱為Haskeys的附加屬性。假如訪問的cookie本身也是個集合,即它是一個多值的cookie,這將返回True。使用Haskeys屬性,可以遍歷完整的Request.Cookies集合,從而獲得所有cookie的列表及它們的值。
For Each objItem In Request.Cookies
If Request.Cookies(objItem).HasKey Then
‘Use another For Each to iterate all subkeys
For Each objItemKey in Request.Cookies(objItem)
Response.Write objItem & “(“ & objItemKey & “) = “_
& Request.Cookies(objItem)(objItemKey) & “<BR>”
Next
Else
‘Print out the cookie string as normal
Response.Write objItem & “ = ”& Request.Cookies(objItem) & “<BR>”
End If
Next
這非常類似于前面的從Request.Form集合中提取多個值的復雜代碼。但是這里可以使用Haskeys屬性來判別每個條目是否為一個集合。而在Form例子里,必須查詢Request.Form(item_name).Count屬性,這是因為Form集合(和所有的除cookie外的其他集合)成員不可能是真正的集合。ASP只是做了“幕后”的工作,得到了每個多條目集合的值。
Form和QueryString的差異
了解了訪問各種ASP集合的技術(shù)以后,需要解決另一個問題是:Form和QueryString集合之間的差異是什么?假如準備使用ASP,毫無疑問應該清楚這種差異,但需要參考HTTP工作方式來重新認識,理解它們。
通過HTTP從Web服務器請求頁面或其他資源,有兩個通用的方法。可使用GET方法直接獲得資源,也可使用POST把值傳給相應資源。GET方法是缺省的,可以看一下本章前面的一個HTTP請求的實例:
7/8/99 10:27:16 Sent GET /Store/Download.asp HTTP/1.1
假如把一個或多個成對的名稱/值附在請求頁面的URL后,就變成請求的查詢字符串,且在QueryString集合中提供給ASP頁面。單擊Web頁面、Email消息或其它文檔的超鏈接,或在瀏覽器的地址欄中輸入地址并按回車,或單擊瀏覽器中的Links或Favorites按鈕,所有這些都要使用GET方法。
因此,對這些動作中傳遞值給ASP的唯一方法是通過QueryString集合,把值附在URL后。
出現(xiàn)在Request.QueryString集合中并被訪問的值,與前面看到的Form集合實例中的工作方式相同。URL和查詢字符串的結(jié)合:
http://mysite.com/process_page.asp?FirstName=Priscilla&LastName=Descartes
可以采用如下方式訪問在QueryString集合中提供的值:
strFirstName = Request.QueryString(“FirstName”) ‘Return “Priscilla”
strLastName = Request.QueryString(“LastName”) ‘Return “Descartes”
strRaw = Request.QueryString
‘Return “FirstName=Priscilla&LastName=Descartes”
窗體的GET和POST方法
在一個頁面內(nèi)使用<FORM>段時,可以設置打開的FORM標記的METHOD屬性值為“GET”或“POST”,缺省值為“GET”。假如使用“GET”或省略其屬性,瀏覽器將該值綁定在頁面所有控件上,成為一個查詢字符串,且附在被請求頁面的URL上。
當這個請求到達Web服務器時,其值由ASP的Request.QueryString集合提供。然而,假如設置METHOD屬性為“POST”,瀏覽器將值包裝進發(fā)送服務器的HTTP報頭中,通過Request.Form集合提供給ASP。
通過來說,可以在所有的HTML窗體中使用POST方法。然而,瀏覽器或服務器的URL字符串長度存在一定的限制。因此,附有長的字符串可能會引起溢出和某些字符串的字符被截掉。同時,查詢字符串出現(xiàn)在瀏覽器的地址欄和所有的保存的鏈接和收藏夾中。不僅如此,還顯露了通過Web服務器時在HTTP請求中不想顯示的值,它也可能出現(xiàn)你的服務器和其他路由服務器的日志文件中。在HTTP請求報頭中的值很少是可見的,并且不出現(xiàn)在日志文件中。
使用POST方法需要注意的小問題是,當用戶重新下載<FORM>時,窗體的值將不再保留,其值為空且必須重新輸入。然而,當附在URL上時,其值被存儲為一個鏈接,將被保留,因此將出現(xiàn)在所有的URL與字符串結(jié)合的請求中,這或許是個優(yōu)點也可能是個缺點,這根據(jù)應用而定(一些瀏覽器在客戶端上能夠在一定范圍內(nèi)自動保留一個頁面上的值)。
另一點是URL與查詢字符串的結(jié)合體不能包含任何空格或其他非法字符,否則的話,Navigator和一些其他的瀏覽器將出現(xiàn)問題。非法字符是那些用來分隔URL和查詢字符串的部分,例如“/”、“:”、“?”和“&”(IE能夠自動將空格轉(zhuǎn)換為正確的格式——加號“+”,但其他的非法字符不能處理)。ASP服務器對象提供URLEncode方法處理這種變換,以后章節(jié)討論相關(guān)內(nèi)容。
查看Request和Response對象內(nèi)容
到目前,主要討論了一些理論問題,沒有列舉特別的實例。因為已經(jīng)討論過的內(nèi)容多數(shù)情況下互相之間是密切相關(guān)的。然而本書為這一章提供了一系列的實例頁面,說明Request和Response對象的大多數(shù)屬性。應用所講過的實例,能夠理解這些頁面,并可進行相應的修改,用它們作為試驗實例。
本章及其他所有章節(jié)的代碼樣例均提供給用戶,可以從Wrox出版社站點下載。
http://webdev.wrox.co.uk/books/2610
http://www.wrox.com/Store/Details.asp?Code=2610
必須首先在Web服務器的WWWRoot內(nèi)的子目錄下安裝實例,然后使用瀏覽器訪問Chapter02子目錄,使用:
http://your_server_name_or_IP/subdirectory_name/Chapter02/Default.asp
這里your_server_name_or_IP/subdirectory_name是安裝下載文件的本地路徑。
1、查看Request對象成員
這提供一個包含選頁的菜單用來試驗Request和Response對象,首先選擇Using the Request Object,如下圖所示:
下圖顯示一個HTML窗體的實例,包含一些預先設置好的值,可以按自己的想法編輯這些值,然后點擊“Submit”按鈕。
這將打開一個頁面,如下圖所示,顯示集合和TotalBytes屬性的全部內(nèi)容。第一屏顯示的是Form、QueryString和Cookies集合。
注意,假如在窗體頁中編輯了HTML控件的值,對于Cookies集合以及其他的集合,在讀者的計算機上的頁面上可能顯示不同的值。
可以從“Form Collection”段中看到窗體上的HTML控件的值如何在ASP的Request.Form集合中表示。也可以用原始的<FORM>頁(名稱為request_form.asp)來試驗和檢測,以了解創(chuàng)建窗體的HTML和如何與相應值相聯(lián)系。
這個頁面后面是ClientCertificate集合。這里是空的,因為服務器不要求客戶端提供證書。下面是的ServerVariables集合,下圖的屏幕圖顯示的是集合中包含的有用的值。
在本書的后面附錄中可以找到所有ServerVariables集合成員的一個列表,及其值的說明。然而,可從前面討論的在請求頁面時從客戶端發(fā)出的HTTP報頭中見到這些成員。當請求收到后,Web服務器也增加它本身的一些值到集合中,正如上面可以看到的運行在IIS 5.0創(chuàng)建的頁面那樣。
1) 頁面是如何工作的
為了創(chuàng)建這個頁面,使用了本章前面在對Form集合和如何訪問其值的討論中所看到的完全相同的代碼。例如,遍歷所有的集合(除Request.Cookies外),使用:
For Each objItem In Request.collection_name
Response.Write objItem & “ = “ & Request.collection_name(objItem) & “<BR>”
Next
遍歷Cookies集合,可以使用:
For Each objItem In Request.Cookies
If Request.Cookies(objItem).HasKeys Then
‘Use another For ... Each to iterate all keys of dictionary
For Each objItemKey in Request.Cookies(objItem)
Resonse.Write objItem objItem & “(“ & objItemKey & “) = “_
& Request.Cookies(objItem)(objItemKey) & “<BR>”
Next
Else
‘Print out the cookie string as normal
Response.Write objItem & “ = “ & Request.Cookies(objItem) & “<BR>”
End If
Next
為獲得TotalBytes屬性,可簡單地使用:
Request.TotalBytes = <% = Request.TotalBytes %><P>
讀者應該注意到,在兩個集合中出現(xiàn)的某些值不是從窗體的HTML控件中直接得到的。QueryString集合包括了兩個名為chapter和sample的值,如下圖所示:
為在請求中創(chuàng)建這兩個值,將一個字符串附在窗體的ACTION屬性的URL上,這是可以接受的。工作方式與附在一個<A>元素的HREF屬性上相類似。查詢字符的值出現(xiàn)在QueryString集合中,且被POST的窗體控件值出現(xiàn)在Form集合中。
<FORM ACTION=”show_request.asp?chapter=2&sample=The+Request+Object” METHOD=”POST”>
為防止非IE類的瀏覽器出現(xiàn)錯誤,必須將查詢字符串中的空格用加號“+”來代替,讀者將在第4章的Server對象的URLEncode方法中看到更多這種情況。
2) 創(chuàng)建客戶端的cookie
為了確保至少有些值出現(xiàn)在Request.Cookies集合中,增加一些客戶端腳本代碼到原始的<FORM>頁面request_form.asp。將創(chuàng)建名稱為VisitCount的多值cookie。另一個cookie是由另一個頁面創(chuàng)建的,且已經(jīng)存在于瀏覽器中。如下圖所示,讀者可以看到另外的cookie。
這是一段窗體被裝載時設置文檔對象的cookies屬性的客戶端代碼:
<SCRIPT LANGUAGE=”JavaScript”>
<!--
documet.cookie = ’VisitCount=VISITS=3&LASTDATE=6%2F4%2F99+10%3A10%3A13+AM’;
//-->
</SCRIPT>
另外,必須將內(nèi)容進行編碼,以便它能被正確地傳送到服務器(同樣的規(guī)則也適用于將查詢字符串附到URL上)。在第4章中,討論Server對象的URLEncode方法時,讀者將了解到更多細節(jié)。
2、查看Response對象的成員
回到Chapter02實例的最初的Default.asp頁面,這次選擇“Using the Response Object”鏈接,這個頁面顯示的是Response對象的集合和屬性的內(nèi)容,且提供到所有Response對象方法的鏈接。
下圖是使用瀏覽器Netsape Communicator 4.61的屏幕,用來證明使用的是純服務器端和跨平臺兼容技術(shù)。需要注意的是Cookies集合是為Response對象而建立的,僅顯示cookie的名稱而不顯示其值。瀏覽該頁時,可能得不到cookie或得到與這個頁面不同的cookie。
(由于豆豆沒有安裝Netsape Communicator 4.61,仍用IE5.5顯示,并無什么區(qū)別)
各種Response屬性說明了將要用來創(chuàng)建HTTP報頭的一些信息。HTTP報頭頁面的其他部分(HTML和文本內(nèi)容)被發(fā)往到客戶端。這些屬性中的一些以及所有的Response對象的方法均有鏈接,允許讀者打開另一個頁面來顯示其使用情況。我們稍后再回到這些頁面。
頁面中的屬性是通過讀取相應的屬性并插入到頁面中創(chuàng)建的。由于這些是動態(tài)鏈接,通過<A>元素來選擇。
<A HREF = ”headers/expiretet_form.asp”>Response.CacheControl</A>
= <% = Resposne.CacheControl %><BR>
鏈接到每個方法是通過<A>鏈接元素,頁面中唯一復雜的部分是Response.Cookies集合。通過只能訪問cookie,讀取Request.Cookies集合中的值。當訪問Response.Cookie集合時,必須在發(fā)送任何輸出到客戶端之前結(jié)束對它的所有引用。因此在頁面的上部,通過遍歷集合創(chuàng)建頁面的HTML放在一個局部字符串變量中。
StrCookies = “”
‘We can only read the key names and not the values because
‘the Response.Cookies collection is ‘write only’
For Each objItem In Response.Cookies
If Response.Cookies(objItem).HasKeys Then
‘Use another For Each to iterate all subkeys
For Each objItemKey in Response.Cookies(objItem)
StrCookies = strCookies & objItem & “(“ &objItemKey & “)<BR>”
Next
Else
‘print out the cookie as normal
strCookies = strCookies & objItem & “<BR>”
End If
Next
然后在頁面的適當點上插入結(jié)果。
<P><DIV CLASS=”subhead”>The Response.Cookies Collection</DIV>
<I><A HREF=”cookies/setcookies.asp”>Response.Cookies</A>
is a write-only collection so the values cannot be displayed</I><BR>
<% = strCookies %>
ASP中的cookie的使用
在前面所看到頁面中,一些集合、屬性和方法已經(jīng)鏈接到其他的頁面,用來顯示Request和Response對象的各個特性細節(jié),我們將在本章的其余的部分研究這些內(nèi)容,我們將學習那些提供給ASP代碼使用的集合、方法和屬性的各種技術(shù)。
在本章前面已經(jīng)看到了如何使用Request.Cookies和Response.Cookies集合來創(chuàng)建和閱讀cookie,點擊上面兩個頁面中的任一個的“Cookies”鏈接時,這個頁面包含一些設置了三個cookie的值的ASP代碼,且在頁面上顯示被執(zhí)行的代碼,如下圖所示:
點擊“Show Cookies”的鏈接時,cookie的內(nèi)容就顯示出來了。這是通過遍歷Request.Cookies集合而得到的,這與在上一頁所用的方式完全相同,如下圖所示:
這個屏幕圖顯示的是運行前面看到的設置cookie值的代碼的結(jié)果??赡軙吹狡渌呀?jīng)存貯在計算機系統(tǒng)里的cookie。然而,假如現(xiàn)在關(guān)閉瀏覽器然后重新打開瀏覽器,然后運行顯示cookie的頁面,除了TimedCookie外,所有的cookie都不見了,這是由于只有這個TimedCookie具有有效期的設置,其他的在瀏覽器關(guān)閉時,自動消失了。
1) cookie中存儲用戶的細節(jié)情況
可以使用cookie來存儲這兩類值:當瀏覽器關(guān)閉時我們不想保存的值(例如用戶的注冊信息)以及在用戶訪問站點時要保留的值。在每種情況下cookie的值對于來自用戶瀏覽器的每個頁面請求的ASP都是可用的。
然而,需要記住的是,cookie只有在對Cookie中的虛擬路徑(path)內(nèi)的頁面發(fā)出請求時,才會發(fā)往服務器。缺省時,假如path的值在cookie中沒有設置,則其值為創(chuàng)建cookie的頁面的虛擬路徑。為使一個cookie發(fā)往一個站點的所有頁面,需要使用path=“/”。
這里是個實例,從自定義的Login頁面中,將用戶的注冊信息存貯在一個cookie中,由于沒有應用有效期,cookie值僅在關(guān)閉這個瀏覽器這前保留:
...
Request.Cookies(“User”)(“UID”) = “<% = Request(“UserName”) %>”
Request.Cookies(“User”)(“PWD”) = “<% = Request(“Password”) %>”
Request.Cookies(“User”).Path = “/adminstuff” ‘Only applies to admin pages
...
現(xiàn)在,在用戶從adminstuff目錄或其子目錄請求的每個頁面中,都可以找到這個cookie。假如它不存在,可以將用戶重定向到注冊頁面:
If (Request.Cookies(“User”)(“UID”) <> “alexhomer”) _
Or (Request.Cookies(“User”)(“PWD”) <> “secret”) Then
Response.Redirect “l(fā)ogin.asp?UserName=” & Request.Cookies(“User”)(“UID”)
End If
...
由于把cookie中的用戶名放在Response.Redirect的URL查詢字符串中,假如在口令輸入時出現(xiàn)錯誤且希望用戶不必重新鍵入用戶名,可以在login.asp頁面中使用它:
<FORM ACTION=”check_user.asp” METHOD=”POST”>
<INPUT TYPE=”TEXT” NAME=”UserName”
VALUE=”<% = Request.QueryString(“UserName”) %>”><P>
<INPUT TYPE=”SUBMIT” VALUE=”LOGIN”>
</FORM>
2) 修改現(xiàn)有的cookie
可以使用ASP修改現(xiàn)有的cookie,但不能只修改cookie中的一個值。當更新一個在Response.Cookies集合中的Cookie時,現(xiàn)有的值將丟失。我們可以用如下代碼創(chuàng)建一個cookie,可以使用:
Response.Cookies(“VisitCount”)(“StartDate”) = dtmStart
Response.Cookies(“VisitCount”)(“LastDate”) = Now
Response.Cookies(“VisitCount”)(“Visits”) = CStr(intVisits)
Response.Cookies(“VisitCount”).Path = “/” ‘Apply to entire site
Response.Cookies(“VisitCount”).Expires = DateAdd(“m”,3,Now)
假如想要更新Visits和LastDate的值,必須先不需改變的所有值,然后重寫整個的cookie:
datDtart = Response.Cookies(“VisitCount”)(“StartDate”)
intVisits = Response.Cookies(“VisitCount”)(“Visits”)
Response.Cookies(“VisitCount”)(“StartDate”) = dtmStart
Response.Cookies(“VisitCount”)(“LastDate”) = Now
Response.Cookies(“VisitCount”)(“Visits”) = Cstr(intVisits)
Response.Cookies(“VisitCount”).Path = “/”
Response.Cookies(“VisitCount”).Expires = DateADD(“m”,3,Now + 1)且對于幾乎所有的其他Response方法和屬性,應該在寫入任何內(nèi)容(即打開<HTML>標記或任何文本或其他的HTML)到響應之前完成這個工作。