深入講解 ASP+ 驗證 (轉自ms 二)
最後更新:2017-02-28
來源:互聯網
上載者:User
asp+ 用戶端 API
有一個可以在客戶機上使用的小型 API,以便在您自己的用戶端代碼中實現各種效果。因為某些常式不可能隱藏,所以理論上講,您可以利用用戶端驗證指令碼所定義的所有變數、特性和函數。不過,其中許多都是可以更改的實施細節。以下總結了我們鼓勵您使用的用戶端對象。
表 3. 用戶端對象
名稱 類型 說明
Page_IsValid Boolean 變數 指出頁面當前是否有效。驗證指令碼總是保持該變數為最新。
Page_Validators 元素數組 這是包含頁面上所有驗證器的數組。
Page_ValidationActive Boolean 變數 指出是否應進行驗證。將此變數設定為 False 可以通過編程關閉驗證。
isvalid Boolean 屬性 每個用戶端驗證器均具有該屬性,指出驗證器當前是否有效。請注意,在 PDC 版本中,該屬性混用大小寫 ("IsValid")。
繞過用戶端驗證
您經常需要執行的一項任務是在頁面上添加“取消”按鈕或導覽按鈕。在這種情況下,即使頁面上有錯誤,您可能也希望使用該按鈕提交頁面。因為用戶端按鈕 "onclick" 事件在表單的 "onsubmit" 事件之前發生,因此可能會避免提交檢查,並繞過驗證。以下說明如何使用 HTML Image 控制項作為“取消”按鈕完成該任務:
<input type=image runat=server
value="取消"
onclick="Page_ValidationActive=false;"
OnServerClick=cmdCancel_Click >
使用 Button 或 ImageButton 控制項執行該任務會出現一些混淆,因為 "onclick" 事件假定為同名的伺服器端事件。您應在用戶端指令碼中設定該事件:
<asp:ImageButton runat=server id=cmdImgCancel
AlternateText="取消"
OnClick=cmdCancel_Click/>
<script language="javascript">
document.all["cmdImgCancel "].onclick =
new Function("Page_ValidationActive=false;");
</script>
解決該問題的另一種方法是:對“取消”按鈕進行一定的設定,使其在返回時不會觸發用戶端指令碼中的提交事件。HtmlInputButton 和 LinkButton 控制項就是這樣的例子。
特殊效果
另一種常見的要求是:在出錯時,除了由驗證器自身顯示的錯誤資訊外,還需要其它一些效果。在這種情況下,您所作的任何修改均需在伺服器或客戶機上同時進行。假設您需要加入一個 Label,根據輸入是否有效來更改顏色。以下是如何在伺服器上實現該任務:
public class ChangeColorPage : Page {
public Label lblZip;
public RegularExpressionValidator valZip;
protected override void OnLoad(EventArgs e) {
lblZip.ForeColor = valZip.IsValid? Color.Black : Color.Red;
}
}
上述方法一切都很完美,但是,只要您如上所述修改驗證,就會發現除非您在客戶機上進行了相同的操作,否則看起來會非常不一致。驗證架構會使您避免許多這種雙重效果,但是無法避免您必須在客戶機和伺服器上同時實現的其它效果。以下是在客戶機上執行同一任務的片段:
<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() {
//如果用戶端驗證未處於活動狀態,則不執行任何操作
if (typeof(Page_Validators) == "undefined") return;
//更改標籤的顏色
lblZip.style.color = valZip.isvalid ? "Black" : "Red";
}
</script>
Beta 1 用戶端 API
對於 Beta 1 版,一些可以從用戶端指令碼調用的函數會造成其它一些情況。
表 4. 從用戶端指令碼調用的函數
名稱 說明
ValidatorValidate(val) 將某個用戶端驗證器作為輸入。使驗證器檢查其輸入並更新其顯示。
ValidatorEnable(val, enable) 擷取一個用戶端驗證器和一個 Boolean 值。啟用或禁用用戶端驗證器。如果禁用,將不會評估用戶端驗證器,用戶端驗證器將總是顯示為有效。
ValidatorHookupControl(control, val) 擷取一個輸入 HTML 元素和一個用戶端驗證器。修改或建立該元素的 change 事件,以便在更改時更新驗證器。該函數適合於基於多個輸入值的自訂驗證器。
其特殊用途是啟用或禁用驗證器。如果您希望驗證只是在特定的情況下生效,可能需要在伺服器和客戶機上同時更改啟用狀態,否則,您會發現使用者無法提交該頁面。
以下是上面的樣本加上一個欄位,該欄位只在取消選中某個複選框時才會進行驗證。
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>
有效性規則和有用的錯誤資訊
每個驗證器會顯示有關特定控制項特定情況的特定錯誤資訊。其中有一些確認是否有效規則,開始,您作為一個開發人員可能會有些混淆,但是如果要產生對使用者有實際協助的錯誤資訊,這些規則是必要的。
所有空的驗證器(除了 RequiredFieldValidator)均會被認為有效。如果某個空值無效,您通常需要一個 RequiredFieldValidator 和一個其它驗證器。您需要這樣做,因為一般情況下,您總是希望對空驗證器和有效性顯示不同的錯誤資訊。您也可以使用不明確的資訊,例如“您必須輸入一個值,並且該值必須在 1 和 10 之間”。
在輸入欄位無法轉換為指定資料類型時使用的另一個特殊規則與 CompareValidator 和 RangeValidator 有關。對指定了 ControlToCompare 的 CompareValidator 進行的有效性評估過程類似如下所述:
如果 ControlToValidate 引用的輸入欄位為空白,則有效。
如果 ControlToValidate 引用的輸入欄位無法轉換成所需資料類型,則無效。
如果 ControlToCompare 引用的輸入欄位無法轉換成所需資料類型,則有效。
輸入欄位轉換成所需資料類型並進行比較。
第三步看起來有些不符合直覺。之所以這樣評估,是因為如果驗證器同時檢查多個欄位的有效性,很難為該驗證器寫出有意義的錯誤資訊。應使用一個獨立的驗證器來報告 ControlToCompare 輸入欄位中的錯誤情況。RangeValidator 的工作方式類似,具有 maximum 和 minimum 屬性。
Enabled、Visible 和 Display 屬性的作用
驗證器的 Enabled、Visible 和 Display 屬性之間的區別可能不是非常明顯。
Display=None 可以用來指定驗證器不直接顯示任何內容,但是仍然進行評估,仍然影響總體的有效性,並且仍可以將錯誤放在客戶機和伺服器上的摘要中。對於用戶端驗證,這些值確定使用可見度樣式特性還是使用顯示樣式特性來開啟或關閉驗證器。對於伺服器端驗證,Display=Dynamic 表示輸入有效時不顯示任何內容,而 Display=Static 表示顯示一個不換行的空格 (" ")。使用最後一個設定是為了表中只包含驗證器的儲存格在有效時,不會摺疊成不顯示任何內容。
為什麼不只使用 Visible=false 使驗證器不可見呢?在 ASP+ 中,控制項的 Visible 屬性有許多含義:Visible=false 的控制項根本不會被處理來預顯示或顯示。正是因為這種含義,驗證器的 Visible=false 意味著不僅不會顯示任何內容,而且無法使用。不會對這樣的驗證器進行評估,不會影響頁面的有效性,也不會將錯誤放在摘要中。
Enabled 則為中性。對於大多數情況,Enabled=false 與 Visible=false 的效果完全相同。在 Beta 1 版或更高版本中,存在一個重要的區別:在用戶端驗證中,禁用的驗證器仍會發送到瀏覽器中,但是處于禁用狀態。您可以使用用戶端指令碼中的 ValidatorEnable 函數啟用該驗證器。
使用 Visible 或 Enabled 控制是否進行驗證時,應注意上述伺服器上的事件順序。或者在驗證之前變更,或者在更改之後重新驗證。否則,它們的 IsValid 值不會將更改反映到屬性上。
CustomValidator 控制項
擴充驗證架構最簡單的方法是使用 CustomValidator 控制項。該控制項既可以用來執行其它驗證控制項無法進行的驗證,也可以執行需要訪問伺服器上資訊(例如資料庫或 Web 服務)的驗證。
如果添加了只定義一個伺服器驗證函式的 CustomValidator,您會注意到,該驗證器並不參與用戶端驗證。當使用者使用 tab 鍵在各欄位之間切換時,CustomValidator 不會更新,並且需要往返伺服器一次以執行其驗證。如果要使用 CustomValidator 執行不需要任何伺服器上資訊的檢查,您也可以使用 ClientValidationFunction 屬性讓驗證器完全參與用戶端驗證。假設您提供了一個 ClientValidationFunction,理想情況下,應與伺服器驗證處理常式執行完全相同的檢查。但實際上,只是執行該驗證的一部分。用戶端驗證函式進行的驗證不要超過在伺服器上執行的驗證,因為駭客很容易繞過該驗證函式。
以下是在客戶機和伺服器上使用 CustomValidator 的一個簡單樣本,只檢查輸入是否是偶數。以下先介紹伺服器函數(在 C# 中):
public bool ServerValidation(object source, string value) {
try {
int i = int.FromString(value);
return ((i % 2) == 0);
} catch {
return false;
}
}
以下是該函數在客戶機上的聲明方法,以及一個執行相同檢查的用戶端驗證函式。這通常是 JScript 形式,不過如果您的目標是 Microsoft® Internet Explorer,也可以使用 VBScript® 形式。
<asp:CustomValidator id="customVal2" runat=server
ErrorMessage="數字不可以被 2 除!"
ControlToValidate="txtCustomData"
OnServerValidationFunction=ServerValidation
ClientValidationFunction="CheckEven" /><br>
Data Field : <asp:TextBox id="txtCustomData" runat="server" />
<script language=javascript>
<!--
function CheckEven(source, value) {
var val = parseInt(value, 10);
if (isNaN(val))
return false;
return ((val % 2) == 0);
}
// -->
</script>
以下是使用 CustomValidator 的一些注意事項:
與所有其它驗證控制項類似(RequiredFieldValidator 除外),如果輸入欄位為空白,則認為 CustomValidator 有效。
如果使用較舊的瀏覽器,或者關閉了用戶端驗證,將無法調用用戶端驗證函式。在定義該函數之前,您不必檢查所用瀏覽器的功能,但是需要確保瀏覽器不會因為定義而造成指令碼錯誤。一定要使您的用戶端代碼作為 HTML 注釋,如下例所示。
兩個參數傳遞到您的用戶端函數中,與傳遞給伺服器函數的參數對應。第一個是用戶端驗證器元素,第二個是 ControlToValidate 指定的控制項值。不過,在客戶機上,您可以選擇不為函數定義參數,這樣也會正常工作。
如果使用 Beta1 版或更高版本,您可以保留 ControlToValidate 為空白。在該模式中,伺服器函數每次往返總會觸發一次,用戶端函數每次嘗試提交時總會觸發一次。您可以使用該特性來驗證其它方法無法驗證的控制項,例如 CheckBoxList 或單獨的選項按鈕。如果條件是基於多個控制項,並且您不希望使用者使用 tab 鍵在頁面上各欄位之間切換時評估該條件,可以使用該方法。
Beta 1 版或更高版本中的另一個選項是掛接多個控制項的 change 事件。方法是加入一些調用用戶端函數 ValidatorHookupControl 的內嵌指令碼,如上所述。
哪些控制項可以被驗證?
要使控制項可以被驗證控制項引用,該控制項必須具有驗證屬性。所有可以驗證的控制項均具有 ValidationPropertyAttribute 屬性,該屬性指明驗證時應讀取的屬性。如果編寫自己的控制項,可以通過提供其中一個特性來指定要使用的屬性,從而使該控制項參與驗證。
要使驗證可以在用戶端正常進行,該屬性必須與用戶端顯示的 HTML 元素的 value 特性對應。許多複雜的控制項(例如 DataGrid 和 Calendar)在用戶端沒有值,只能在伺服器上進行驗證。因此,只有最接近 HTML 元素的控制項才可以參與驗證。此外,控制項必須在用戶端具有單個邏輯值。因此,RadioButtonList 可以被驗證,但是 CheckBoxList 不可以。
到此為止
上述對 ASP+ 驗證的講解可能已經超過了您要瞭解的內容。盡情享用吧!