ASP.NET入門隨想之檢票的老太太_實用技巧

來源:互聯網
上載者:User
   德國足協告誡那些可能前往德國觀看2006年世界盃賽的球迷要提防假票,不要從非代理商和票販子手中購票。世界盃門票都是高科技產品,門票被植入微晶片,只有通過合法途徑取得門票的球迷才能入場。假票現象在近些年的足球大賽上泛濫成災,德國足協希望能通過宣傳避免世界盃球迷成為其受害者。

  ■ 驗明正身 - 資料有效性

  世界盃萬人矚目但門票有限,所以有人造假有人買假,安聯球場的大門前站幾位檢票員必不可少,而我們的程式有時也一樣。當你接到一個累積數年的資料表時,發現單單聯絡電話都有23種格式時,你是否也感歎到,在使用者提交資料時系統也需要靠檢票員來驗證一下?可是我們還是發現象資料驗證這樣的內容往往容易被人忽視,許多系統常讓拿著公車票的傢伙混進球場撒野,各種資料如同發情野馬一般長驅直入,先不說安全問題,從資料有效性的角度看,幾年後它會象黴菌一樣讓整個資料庫腐爛變質,垃圾成堆。不過常會有另一種聲音在耳旁響起:"搞那麼複雜做什麼呀,這個系統、甚至是這個企業沒等黴菌開始起作用,它就掛了!"

  應用程式必須確保系統的資料有效性有二層含義:一是格式驗證,要確保資料屬於系統設計時定義的類型、範圍,甚至是行業的特定格式,這通常在系統的UI層來完成驗證;二是邏輯驗證,資料間往往符合特定的商務邏輯規則,資料操作不能破壞其間邏輯關係而造成系統異常,這通常在系統的底層來完成驗證。本文主要討論前者的實現。

  不過許多系統為了保持資料有效性常常矯枉過正,介面充斥著擁有複雜輸入格式限制的文本輸入框,要求使用者花費大量時間來進行自我資料校正,填寫個表單比高考畫框框還要讓人費勁,企業使用者還好辦些,最多抗議兩聲也就接受,互連網使用者可不吃這一套,來點創意!

  ■ 檢票的老太太們 - 驗證器架構

  WEB應用程式是基於表單來輸入資料。為了確保資料有效性,我們必須在服務端對輸入資料進行檢驗,但考慮到使用者感受,往往又在用戶端插入些javascript指令碼。用戶端驗證就像我們呼吸空氣時的鼻子,先把顆粒物雜質等阻擋在外面,從而大大減輕了肺的負擔;伺服器端驗證是構建安全Web應用程式必需的,只有伺服器端驗證才可以提供真正應用程式級的安全。雙重校正,瑣碎無聊,怪不得沒幾人喜歡。

  .NET首先將驗證器與驗證對象分離成兩個部份,驗證對象暴露驗證屬性,檢票員們分頭監督驗證對象,完成資料校正,比較複雜的校正可以讓幾位檢票員一起守著;每個頁面需要一位領頭,讓她拿著名單,依次催促頁面內每個驗證器對所轄輸入欄位進行驗證,匯總出結果;最後頁面需要某些控制項能夠自動觸發驗證,這個角色通常是由帶有回傳功能的Button類控制項來扮演,如圖13-1所示。


  參與Web表單驗證的伺服器控制項必須實現IValidator介面,這是檢票員們的共同特徵。用Volidate方法完成校正過程,得出一個結果值IsValid屬性,包含拒絕允許存取的理由ErrorMessage屬性。於是有如下定義:

public interface IValidator{
 string ErrorMessage{set;get;}
 bool IsValid{set;get;}
 void Volidate{};
}

  作為校正行為的原子觸發單位,頁面類設定了一些必要的成員:Page.Validators集合是頁面的驗證器容器,Page.Validate方法將依次調用容器中每個驗證器的Validate方法更新各自的IsValid屬性,Page.Valid屬性用於匯總頁面的校正結果,它就是頁面的心靈之鎖。

  CausesValidation屬性是引起回傳控制項的公用屬性,為真時控制項在Click事件處理之前自動調用Page.Validate方法,這樣使得我們在大多時候不需要顯式地去調用Page.Validate方法即可完成校正過程。

  ■ 模範 - BaseValidator類及用戶端驗證

  儘管在ASP.NET中,任何通過實現IValidate介面的類都可以被認為是驗證器,但在實際應用中,我們通常把驗證器設計成伺服器控制項。

  BaseValidator是派生自Label類的抽象基類,除了實現IValidator介面,主要執行校正必需的各種通用任務,包括從被驗證對象提取值、定義校正抽象方法、產生用戶端驗證指令碼、完成在Page.Validators集合中註冊等等。通過繼承它,我們只要集中精力去實現伺服器端和用戶端的驗證邏輯就可以實現自訂驗證器。下例為一檢查CheckBoxList是否有勾選1個以上的自訂驗證器範例。

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

namespace essay.Controls{
 //派生於BaseValidator基類的自訂驗證器
 public class RequiredCheckBoxListValidator : BaseValidator {
  private ListControl m_ListCtl;
  //啟用用戶端驗證
  public RequiredCheckBoxListValidator(){
   base.EnableClientScript = true;
  }
  //確定由ControlToValidate指定的被驗證控制項是否有效
  protected override bool ControlPropertiesValid(){
   Control webControl = this.FindControl(ControlToValidate);
   if (webControl != null){
    m_ListCtl = (ListControl)webControl;
    return true;
   }
   else
    return false;
  }
  //定義校正規則
  protected override bool EvaluateIsValid(){
   return (m_ListCtl.SelectedIndex != -1);
  }
  protected override void OnPreRender(EventArgs e) {
   if (this.EnableClientScript) this.GenerateScript();
   base.OnPreRender(e);
  }
  //產生並向頁面注入用戶端驗證指令碼
  protected void GenerateScript(){
   StringBuilder sb_Script = new StringBuilder();
   sb_Script.Append("<script language=\"javascript\">\n");
   sb_Script.Append("function cb_vefify(val) {\n");
   sb_Script.Append("var isValid=false;\n");
   sb_Script.Append("var val = document.all[document.all[\""+this.ID+"\"].controltovalidate];\n");
   sb_Script.Append("var col = val.all;\n");
   sb_Script.Append("if ( col != null )\n");
   sb_Script.Append("for ( i = 0; i < col.length; i++ ) \n");
   sb_Script.Append("if (col.item(i).tagName == \"INPUT\") \n");
   sb_Script.Append("if ( col.item(i).checked )isValid=true; \n");
   sb_Script.Append("return isValid;");
   sb_Script.Append("}\n");
   sb_Script.Append("</script>");
   this.Page.RegisterClientScriptBlock("RBLScript", sb_Script.ToString());
   //通過設定驗證器的evaluationfunction attribute來指定其用戶端驗證邏輯
   this.Attributes["evaluationfunction"] = "cb_vefify";
  }
 }
}

  ■ 我很醜可是我很能幹- Regex(Regular Expression)

  Regex被用於描述某一類特定格式的字串方法,能簡潔地、能幾何倍數地改善文本處理效率,但它不招人疼所以讓人厭惡,原因並不是概念有多高深,主要是它長得太醜!一個字串是否符合某一類特定格式的字串,關鍵在於它是否符合這個特定格式的多個匹配規則。

  理解Regex的鑰匙在於提煉每條匹配規則的三個要素:字元子集、重複次數與位置。例字串"兩位元字開頭三位英文字母結尾",寫Regex之前需要我們這麼變換句式:"開頭 數字{2位} 任一字元{0或多位} 字母{3位} 結尾",Regex為"^ [0-9]{2} [\s\S]* [a-zA-Z]{3} $"。

  在每條匹配規則中,可能出現的字元子串有個範圍,屬於固定的字元子集,Regex用常量、地區和邏輯運算來表示這個集合,如圖13-2所例,值得注意是部份字元已被定義成元字元,具有特殊的含義。


  每條匹配規則中,其字元子集可能出現重複,可以用兩種方法表示:一是緊跟著字元子集後加個大括弧,內標數字,另一種用元字元表示,如圖13-3例。每條匹配規則中字元子集的位置由其在Regex中的位置決定,整個字串開頭用"^"表示,結尾用"$"表示。


  在很多時候,兩條或以上的匹配規則可能要用到同一個字元子集,如html標記中,標籤聲明應當是同一字元子集,比如"<div>……</div>"。如果要定義一個字元子集以便其後引用,可用小括弧標識,用"\數字"引用。

  Regex的應用範圍很廣,除了資料校正外,UBB論壇、頁面動態轉靜態、搜尋技術等時常出現它的身影,"我很醜可是我很能幹",在這裡我們僅僅只是探討運算式的書寫方法。最後用兩個執行個體總結,如圖13-4所示。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.