top
Loading...
ASP.NET2.0服務器控件之驗證控件示例
上一篇文章中,我們講解了有關實現驗證控件的一些知識。那些內容將為開發人員實現驗證控件奠定一定基礎。為了幫助讀者更好的理解驗證控件的實現方法,本文將首先介紹常見驗證控件的實現步驟,然后,通過一個典型示例說明驗證控件的實現方法。

1. 驗證控件實現步驟

在創建驗證控件過程中,需要實現服務器端驗證和客戶端驗證等核心內容。下面列舉了驗證控件的常見實現步驟。

(1)驗證控件類應由BaseValidator基類繼承。這樣可使驗證控件自動繼承參與驗證框架所需要的功能。例如,通過繼承BaseValidator的ControlToValidate屬性,實現驗證控件與驗證目標控件的關聯。

(2)實現驗證控件所特有的一些屬性。開發人員可根據應用需求,從方便實用的角度出發定義這些特有屬性。

(3)重寫AddAttributesToRender方法,將特有屬性及相關內容添加到控件呈現中。當實現客戶端驗證代碼時可能需要引用相關呈現內容。

(4)重寫EvaluateIsValid方法,為驗證控件添加服務器端驗證邏輯。

(5)重寫PreRender事件的事件處理方法OnPreRender,除調用基類實現方法外,還要實現對客戶端驗證腳本文件的注冊。

(6)編寫與驗證控件一起打包的客戶端驗證腳本文件,并且將其放置到正確的目錄中。

通過以上的一個或者幾個步驟,開發人員就可以實現一個基本的驗證控件。在實現過程中,服務器端驗證邏輯和客戶端驗證邏輯必須保持一致,否則,即使輸入數據通過了客戶端驗證,也無法通過服務器端驗證。下面將通過一個典型實例來進一步說明驗證控件的實現方法,以加深讀者的理解。

2、典型應用

本節將使用上文所介紹的開發驗證控件的方法,創建一個名為TelNumValidator的驗證控件。該控件用于驗證用戶輸入的電話號碼是否符合規則。如果不符合規則,那么動態提示錯誤信息。其效果如圖1。


圖1 效果圖(輸入錯誤狀態下)

如圖1所示,頁面中主要包括了一個TextBox文本框和一個提交按鈕。用戶必須輸入正確格式的電話號碼,才能夠通過驗證。圖1中,由于沒有輸入正確的電話號碼,當單擊提交按鈕時,則無法實現提交頁面。同時,頁面還分紅藍兩種顏色給出了提示信息。下文詳細講解了驗證控件的實現過程。

首先,在實現TelNumValidator控件之前,必須進一步明確驗證條件。

對于國內電話號碼,一般為兩種模式:一種是區號為3位,電話號碼為8位,另一種是區號為4位,電話號碼為7位。據此,可得出用于驗證的正則表達式:“d{3}-d{8}|d{4}-d{7}”。無論是服務器端驗證邏輯,還是客戶端驗證邏輯,都必須遵從以上驗證條件。只有符合這兩種模式的輸入數據才能夠通過驗證。

下面列出了驗證控件TelNumValidator的服務器端驗證的源代碼。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text.RegularExpressions;

namespace WebControlLibrary
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:TelNumValidator runat=server>
</{0}:TelNumValidator>")
]

public class TelNumValidator : BaseValidator
{
// 定義私有變量,其中_clientFileUrl表示JavaScript文件存儲目錄
// ValidationExpression表示正則表達式

private string _clientFileUrl = "ClientFiles/";
private const string ValidationExpression = @"(d{3}-d{8}|d{4}-d{7})";
// 定義屬性ClientFileUrl,用于獲取或設置腳本相對路徑
[
Description("獲取或設置腳本相對路徑"),
DefaultValue("ClientFiles/"),
Category("Appearance")
]

public string ClientFileUrl
{
get
{ return _clientFileUrl; }
set
{ _clientFileUrl = value; }
}
//重寫AddAttributesToRender,為驗證控件添加特殊屬性evaluationfunction和validationexp
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
if (RenderUplevel)
{
writer.AddAttribute("evaluationfunction", "TelNumValidatorEvaluateIsValid", false);
writer.AddAttribute("validationexp", ValidationExpression);
}
}
//重寫EvaluateIsValid方法,定義服務器端驗證邏輯
protected override bool EvaluateIsValid()
string controlValue = GetControlValidationValue(ControlToValidate);
if (controlValue == null)
{
return true;
}
controlValue = controlValue.Trim();
try
{
Match m = Regex.Match(controlValue, ValidationExpression);
return (m.Success && (m.Index == 0) && (m.Length == controlValue.Length));
}
catch
{
return false;
}
}
//重寫OnPreRender方法,注冊客戶端腳本程序
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (RenderUplevel)
{Page.ClientScript.RegisterClientScriptBlock ( typeof(TelNumValidator),
"ClientValidator", GetClientFileUrl ( "ClientValidator.js" ));
}
}

// 實現輔助函數GetClientFileUrl,用于獲取JavaScript文件的完整路徑

private string GetClientFileUrl(string fileName)
{
string tempClient = String.Format("<script language="javascript" src="{0}"></script>", (ClientFileUrl + fileName));
return tempClient;
}
}

從以上代碼可知,TelNumValidator控件的實現,是按照上文說明的驗證控件實現步驟編寫的。該類實現了以下重要邏輯:

(1)驗證控件類TelNumValidator類從BaseValidator基類繼承,因此,該類自動繼承了通用驗證控件應該具備的屬性、方法和事件。

(2)定義用于獲取或設置腳本相對路徑的屬性ClientFileUrl,默認值為“ClientFiles/”。通過該屬性頁面開發者可自定義客戶端驗證腳本文件的目錄,這樣可增加控件的靈活性。

(3)重寫AddAttributesToRender方法,為控件添加特性evaluationfunction和validationexp。特性evaluationfunction對應的值是進行客戶端驗證的方法名。特性validationexp對應的值是用于驗證的正則表達式,通過將其呈現到客戶端,那么客戶端驗證腳本即可使用該表達式。

(4)重寫EvaluateIsValid方法,定義服務器端驗證邏輯。(5)重寫OnPreRender方法,注冊客戶端腳本文件ClientValidator.js。

讀者可能已經注意到該驗證控件需要實現客戶端驗證,而客戶端驗證包含在ClientValidator.js文件中。默認情況下,該文件位于“ClientFiles”文件夾中。

下面列出客戶端驗證文件ClientValidator.js的源代碼。

function TelNumValidatorEvaluateIsValid(val)
{
var validationexp = val.validationexp;
var valueToValidate = ValidateTrim(ValidateGetValue(val.controltovalidate));
var rx = new RegExp(validationexp);
var matches = rx.exec(valueToValidate);
return (matches != null && valueToValidate == matches[0]);
}

/* 獲取驗證目標控件的輸入數據 */

function ValidateGetValue(id)
{
var control;
control = document.all[id];
if (typeof(control.value) == "string")
{
return control.value;
}
if (typeof(control.tagName) == "undefined" && typeof(control.length) == "number")
{
var j;
for (j=0; j < control.length; j++)
{
var inner = control[j];
if (typeof(inner.value) == "string" && (inner.type != "radio" || inner.status == true))
{
return inner.value;
}
}
}
else
{
return ValidatorGetValueRecursive(control);
}
return "";
}

/* 去除空格處理 */

function ValidateTrim(s)
{
var m = s.match(/^s*(S+(s+S+)*)s*$/);
return (m == null) ? "" : m[1];
}

由上代碼可知,ClientValidatior.js文件中僅包括一個主方法TelNumValidatorEvaluateIsValid。該方法實現了與服務器端驗證中,EvaluateIsValid方法相同的邏輯。同時,還包括兩個輔助方法ValidateGetValue和ValidateTrim。前者用于獲取驗證目標控件的輸入數據,后者用于去除空格處理。

為了測試當前自定義驗證控件,下面列舉了Default.aspx頁面源代碼。

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register TagPrefix="Sample" Assembly="WebControlLibrary" Namespace="WebControlLibrary" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>實現一個驗證控件</title>
</head>
<body>
<form id="form1" runat="server">
<div style="font-size: small;">
<asp:TextBox ID="textbox" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="提交"></asp:Button>
<Sample:TelNumValidator ID="demo1" runat="server" Display="dynamic" ControlToValidate="textbox" Text="請輸入有效的電話號碼" ErrorMessage="正確的格式為010-12345678或者0123-1234567"></Sample:TelNumValidator>
<br /><br />
<asp:ValidationSummary runat="server" ForeColor="blue" DisplayMode="singleParagraph" HeaderText="錯誤信息:" ID="ValidationSummary1"></asp:ValidationSummary>
</div>
</form>
</body>
</html>

在以上實現中,請讀者重點關注自定義驗證控件的屬性設置。該控件主要設置了以下幾個重要屬性。

(1)ControlToValidate屬性,通過設置該屬性,從而實現了驗證控件TelNumValidator和驗證目標控件TextBox之間的關聯。

(2)Display屬性,通過設置該屬性可設置錯誤信息顯示方式。

(3)ErrorMessage,該屬性用于獲取或設置驗證失敗時ValidationSummary控件中顯示的錯誤信息的文本。為此,在代碼中還設置了一個對應的ValidationSummary控件。

(4)Text,該屬性用于獲取或設置驗證失敗時驗證控件中顯示的文本。

需要注意的是以上4個屬性都繼承自BaseValidator基類。另外,如果應用程序部署需要,開發人員還可以修改驗證控件的ClientFileUrl屬性。

3. 小結

本文通過一個典型示例說明了驗證控件的實現方法。相信讀者已經能夠感到,如果實現高質量的驗證控件,開發人員必須掌握多方面的知識,尤其是JavaScript語言等。另外,本文所涉及的JavaScript代碼被包含在js文件中。開發人員也可以將這些代碼作為資源文件編譯到驗證控件的dll文件中。這種實現方法非常有利于控件的部署工作。有興趣的讀者可以試一試。
作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗