明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

深入講解 ASP+ 驗(yàn)證(3)

[摘要]客戶端的驗(yàn)證 如果您的頁面啟用了客戶端驗(yàn)證,則在往返過程中會發(fā)生完全不同的事件序列?蛻舳说尿(yàn)證使用客戶端 JScript® 實(shí)現(xiàn)。實(shí)現(xiàn)該驗(yàn)證不需要任何二進(jìn)制組件。 盡管 JScri...
客戶端的驗(yàn)證

如果您的頁面啟用了客戶端驗(yàn)證,則在往返過程中會發(fā)生完全不同的事件序列?蛻舳说尿(yàn)證使用客戶端 JScript® 實(shí)現(xiàn)。實(shí)現(xiàn)該驗(yàn)證不需要任何二進(jìn)制組件。

盡管 JScript 語言的標(biāo)準(zhǔn)化做得很好,但是用于與瀏覽器中的 HTML 文檔交互的文檔對象模型 (Document Object Model, DOM) 沒有廣泛采用的標(biāo)準(zhǔn)。因此,客戶端的驗(yàn)證只在 Internet Explorer 4.0 和更高版本中進(jìn)行,因?yàn)樵擈?yàn)證的對象是 Internet Explorer DOM。

從服務(wù)器的角度來說,客戶端的驗(yàn)證只意味著驗(yàn)證控件將不同的內(nèi)容發(fā)送到 HTML 中。除此之外,其事件序列完全相同。服務(wù)器端的檢查仍然執(zhí)行。盡管看起來似乎多余,但是卻十分重要,因?yàn)椋?

某些驗(yàn)證控件可能不支持客戶端腳本。有一個(gè)很好的例子:如果要同時(shí)使用 CustomValidator 和服務(wù)器驗(yàn)證函數(shù),但是沒有客戶機(jī)驗(yàn)證函數(shù)。
安全性注意事項(xiàng)。某些人可以很容易得到一個(gè)包含腳本的頁面,然后禁用或更改該頁面。您不應(yīng)利用腳本來阻止壞數(shù)據(jù)進(jìn)入您的系統(tǒng),而只應(yīng)是為了用戶得到更快的反饋。因此,如果要使用 CustomValidator,則不應(yīng)提供沒有相應(yīng)服務(wù)器驗(yàn)證函數(shù)的客戶機(jī)驗(yàn)證函數(shù)。
每個(gè)驗(yàn)證控件都可以確保將一個(gè)標(biāo)準(zhǔn)的客戶端腳本塊發(fā)送到頁面中。實(shí)際上,這只是一小部分代碼,其中包含對腳本庫 WebUIValidation.js 中的代碼的引用。這個(gè)腳本庫文件包含客戶端驗(yàn)證的所有邏輯,該文件需單獨(dú)下載,并且可以存儲在瀏覽器的緩存中。

關(guān)于腳本庫

因?yàn)轵?yàn)證 Web 控件腳本在腳本庫中,所以不必將所有客戶端驗(yàn)證的代碼直接發(fā)送到頁面中,盡管表面上似乎是這樣做的。主要的腳本文件引用類似如下所示:

<script language="javascript"
src="/_aspx/1.0.9999/script/WebUIValidation.js"></script>

默認(rèn)情況下,腳本文件將安裝在 "_aspx" 目錄中默認(rèn)的根目錄下,并使用相對于根的腳本 include 指令調(diào)用,該指令以正斜線開頭。該引用表明每個(gè)單獨(dú)的對象不必包含腳本庫,同一臺計(jì)算機(jī)上的所有頁面可以引用同一個(gè)文件。您會注意到,該路徑中還有一個(gè)公用的語言運(yùn)行時(shí)版本號,以便不同的運(yùn)行時(shí)版本可以在同一臺計(jì)算機(jī)上運(yùn)行。

如果查看一下您默認(rèn)的虛擬根目錄,您會找到該文件并查看其中的內(nèi)容。這些文件的位置在 config.web 文件中指定。config.web 文件是一個(gè)用于大多數(shù) ASP+ 設(shè)置的 XML 文件。以下是該文件中位置的定義:

<webcontrols
clientscriptslocation="/_aspx/{0}/script/"
/>

鼓勵(lì)您閱讀該腳本,以便深入了解發(fā)生的事件。不過,建議您不要修改這些腳本,因?yàn)樗鼈兊墓δ芘c特定的運(yùn)行時(shí)版本緊密相連。在運(yùn)行時(shí)版本更新時(shí),這些腳本可能也需要相應(yīng)的更新,您將或者放棄更改,或者面臨腳本不工作的問題。如果特定項(xiàng)目必須更改這些腳本,先備份這些腳本,然后將您的項(xiàng)目指向備份文件,方法是使用私有的 config.web 文件替代這些文件的位置。如果字符串中包含格式指令 "{0}",運(yùn)行時(shí)版本號將替換該指令。最好將該位置更改為一個(gè)相對引用或絕對引用。

禁用客戶端的驗(yàn)證

有時(shí)您可能不希望進(jìn)行客戶端驗(yàn)證。如果輸入字段的數(shù)目很少,客戶端驗(yàn)證可能用處不大。您畢竟每次都要有一個(gè)需要往返服務(wù)器一次的邏輯。您會發(fā)現(xiàn)客戶機(jī)上動(dòng)態(tài)出現(xiàn)的信息對您的布局會有負(fù)面影響。

要禁用客戶端驗(yàn)證,應(yīng)使用 Page 指令 "clienttarget=downlevel"。該指令類似以下 ASPX 文件的開頭:

<%@ Page Language="c#" clienttarget=downlevel %>

該指令的默認(rèn)值為 "auto",表示您只對 Microsoft Internet Explorer 4.0 或更高版本進(jìn)行客戶端驗(yàn)證。

注意: 不幸的是,在 Beta 1 中,該指令并非僅僅是禁用驗(yàn)證,同時(shí)還會使所有 Web 控件使用 HTML 3.2 標(biāo)記來處理,這可能會產(chǎn)生意想不到的結(jié)果。最終版本提供了更好的方法來控制這個(gè)問題。

客戶端事件序列

該序列是在運(yùn)行包含客戶端驗(yàn)證的頁面時(shí)發(fā)生的事件序列:

在頁面載入瀏覽器時(shí),需要對每個(gè)驗(yàn)證控件進(jìn)行一些初始化。這些控件作為 <span> 標(biāo)記發(fā)送,其 HTML 特性與服務(wù)器上的特性最接近。最重要的是,此時(shí)會將驗(yàn)證器引用的所有輸入元素“掛接”。被引用的輸入元素將修改其客戶端事件,以便在每次輸入更改時(shí)調(diào)用驗(yàn)證例程。
腳本庫中的代碼將在用戶使用 tab 鍵在各字段之間切換時(shí)執(zhí)行。某個(gè)獨(dú)立的字段更改時(shí),將重新評估驗(yàn)證條件,根據(jù)需要使驗(yàn)證器可見或不可見。
當(dāng)用戶嘗試提交表單時(shí),將重新評估所有驗(yàn)證器。如果這些驗(yàn)證器全部有效,表單將提交給服務(wù)器。如果存在一處或多處錯(cuò)誤,則會出現(xiàn)下述情況:
提交被取消。表單并不提交給服務(wù)器。
所有無效的驗(yàn)證器均可見。
如果某個(gè)驗(yàn)證摘要包含 ShowSummary=true,則將收集來自驗(yàn)證控件的所有錯(cuò)誤,并使用這些錯(cuò)誤更新其內(nèi)容。
如果某個(gè)驗(yàn)證摘要包含 ShowMessageBox=true,則將收集錯(cuò)誤,并在客戶機(jī)的信息框中顯示這些錯(cuò)誤。
因?yàn)樵诿看屋斎敫臅r(shí)或提交時(shí)會執(zhí)行客戶端驗(yàn)證控件,所以在客戶機(jī)上通常會評估這些驗(yàn)證控件兩次或兩次以上。請注意,提交后,仍將會在服務(wù)器上對這些驗(yàn)證控件進(jìn)行重新評估。

客戶端 API

有一個(gè)可以在客戶機(jī)上使用的小型 API,以便在您自己的客戶端代碼中實(shí)現(xiàn)各種效果。因?yàn)槟承├滩豢赡茈[藏,所以理論上講,您可以利用客戶端驗(yàn)證腳本所定義的所有變量、特性和函數(shù)。不過,其中許多都是可以更改的實(shí)施細(xì)節(jié)。以下總結(jié)了我們鼓勵(lì)您使用的客戶端對象。

表 3. 客戶端對象

名稱 類型 說明
Page_IsValid Boolean 變量 指出頁面當(dāng)前是否有效。驗(yàn)證腳本總是保持該變量為最新。
Page_Validators 元素?cái)?shù)組 這是包含頁面上所有驗(yàn)證器的數(shù)組。
Page_ValidationActive Boolean 變量 指出是否應(yīng)進(jìn)行驗(yàn)證。將此變量設(shè)置為 False 可以通過編程關(guān)閉驗(yàn)證。
isvalid Boolean 屬性 每個(gè)客戶端驗(yàn)證器均具有該屬性,指出驗(yàn)證器當(dāng)前是否有效。請注意,在 PDC 版本中,該屬性混用大小寫 ("IsValid")。


繞過客戶端驗(yàn)證

您經(jīng)常需要執(zhí)行的一項(xiàng)任務(wù)是在頁面上添加“取消”按鈕或?qū)Ш桨粹o。在這種情況下,即使頁面上有錯(cuò)誤,您可能也希望使用該按鈕提交頁面。因?yàn)榭蛻舳税粹o "onclick" 事件在表單的 "onsubmit" 事件之前發(fā)生,因此可能會避免提交檢查,并繞過驗(yàn)證。以下說明如何使用 HTML Image 控件作為“取消”按鈕完成該任務(wù):

<input type=image runat=server
value="取消"
onclick="Page_ValidationActive=false;"
OnServerClick=cmdCancel_Click >

使用 Button 或 ImageButton 控件執(zhí)行該任務(wù)會出現(xiàn)一些混淆,因?yàn)?"onclick" 事件假定為同名的服務(wù)器端事件。您應(yīng)在客戶端腳本中設(shè)置該事件:

<asp:ImageButton runat=server id=cmdImgCancel
AlternateText="取消"
OnClick=cmdCancel_Click/>

<script language="javascript">
document.all["cmdImgCancel "].onclick =
new Function("Page_ValidationActive=false;");
</script>

解決該問題的另一種方法是:對“取消”按鈕進(jìn)行一定的設(shè)置,使其在返回時(shí)不會觸發(fā)客戶端腳本中的提交事件。HtmlInputButton 和 LinkButton 控件就是這樣的例子。

特殊效果

另一種常見的要求是:在出錯(cuò)時(shí),除了由驗(yàn)證器自身顯示的錯(cuò)誤信息外,還需要其它一些效果。在這種情況下,您所作的任何修改均需在服務(wù)器或客戶機(jī)上同時(shí)進(jìn)行。假設(shè)您需要加入一個(gè) Label,根據(jù)輸入是否有效來更改顏色。以下是如何在服務(wù)器上實(shí)現(xiàn)該任務(wù):

public class ChangeColorPage : Page {
public Label lblZip;
public RegularExpressionValidator valZip;

protected override void OnLoad(EventArgs e) {
lblZip.ForeColor = valZip.IsValid? Color.Black : Color.Red;
}
}

上述方法一切都很完美,但是,只要您如上所述修改驗(yàn)證,就會發(fā)現(xiàn)除非您在客戶機(jī)上進(jìn)行了相同的操作,否則看起來會非常不一致。驗(yàn)證框架會使您避免許多這種雙重效果,但是無法避免您必須在客戶機(jī)和服務(wù)器上同時(shí)實(shí)現(xiàn)的其它效果。以下是在客戶機(jī)上執(zhí)行同一任務(wù)的片段:

<asp:Label id=lblZip runat=server
Text="Zip Code:"/>
<asp:TextBox id=txtZip runat=server
OnChange="txtZipOnChange();" /></asp:TextBox><br>
<asp:RegularExpressionValidator id=valZip runat=server
ControlToValidate=txtZip
ErrorMessage="無效的郵政編碼"
ValidationExpression="[0-9]{5}" /><br>

<script language=javascript>
function txtZipOnChange() {
//如果客戶端驗(yàn)證未處于活動(dòng)狀態(tài),則不執(zhí)行任何操作
if (typeof(Page_Validators) == "undefined") return;
//更改標(biāo)簽的顏色
lblZip.style.color = valZip.isvalid ? "Black" : "Red";
}
</script>

Beta 1 客戶端 API

對于 Beta 1 版,一些可以從客戶端腳本調(diào)用的函數(shù)會造成其它一些情況。

表 4. 從客戶端腳本調(diào)用的函數(shù)

名稱 說明
ValidatorValidate(val) 將某個(gè)客戶端驗(yàn)證器作為輸入。使驗(yàn)證器檢查其輸入并更新其顯示。
ValidatorEnable(val, enable) 獲取一個(gè)客戶端驗(yàn)證器和一個(gè) Boolean 值。啟用或禁用客戶端驗(yàn)證器。如果禁用,將不會評估客戶端驗(yàn)證器,客戶端驗(yàn)證器將總是顯示為有效。
ValidatorHookupControl(control, val) 獲取一個(gè)輸入 HTML 元素和一個(gè)客戶端驗(yàn)證器。修改或創(chuàng)建該元素的 change 事件,以便在更改時(shí)更新驗(yàn)證器。該函數(shù)適合于基于多個(gè)輸入值的自定義驗(yàn)證器。


其特殊用途是啟用或禁用驗(yàn)證器。如果您希望驗(yàn)證只是在特定的情況下生效,可能需要在服務(wù)器和客戶機(jī)上同時(shí)更改激活狀態(tài),否則,您會發(fā)現(xiàn)用戶無法提交該頁面。

以下是上面的示例加上一個(gè)字段,該字段只在取消選中某個(gè)復(fù)選框時(shí)才會進(jìn)行驗(yàn)證。

public class Conditional : Page {
public HtmlInputCheckBox chkSameAs;
public RequiredFieldValidator rfvalShipAddress;
protected override void Validate() {
bool enableShip = !chkSameAs.Checked;
rfvalShipAddress.Enabled = enableShip;
base.Validate();
}
}

以下是客戶端等效的代碼:

<input type=checkbox runat=server id=chkSameAs
onclick="OnChangeSameAs();" >與付款地址相同<br>
<script language=javascript>
function OnChangeSameAs() {
var enableShip = !event.srcElement.status;
ValidatorEnable(rfvalShipAddress, enableShip);
}
</script>