asp.net|伺服器|控制項|樣本 在
上一篇文章中,我們講解了有關實現驗證控制項的一些知識。那些內容將為開發人員實現驗證控制項奠定一定基礎。為了協助讀者更好的理解驗證控制項的實現方法,本文將首先介紹常見驗證控制項的實現步驟,然後,通過一個典型樣本說明驗證控制項的實現方法。
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位。據此,可得出用於驗證的Regex:“\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表示Regex
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對應的值是用於驗證的Regex,通過將其呈現到用戶端,那麼用戶端驗證指令碼即可使用該運算式。
(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檔案中。這種實現方法非常有利於控制項的部署工作。有興趣的讀者可以試一試。