#眉標=Enterprise Library #副標=設計模型套件系列(11) #大標=資料驗証機制(下) #作者=文/圖 王寧疆 ============= 程式1 public class ValidateAttributeProduct { [RangeValidator(0, RangeBoundaryType.Inclusive, 1000, RangeBoundaryType.Inclusive, MessageTemplate="ProductID必須是介於1~1000的數字", Ruleset = "AttributeRuleSet")] public int ProductID; //驗証ProductID變數的內容必須是介於1~1000的數字 [StringLengthValidator(1, 4, MessageTemplate = "ProductName的長度必須是介於1~4個字元的字串", Ruleset = "AttributeRuleSet")] public string ProductName; //驗証ProductName變數的內容的長度必須是介於1~4個字元的字串 [RangeValidator(0, RangeBoundaryType.Inclusive, 100, RangeBoundaryType.Inclusive, MessageTemplate = "SupplierID必須是介於1~100的數字", Ruleset = "AttributeRuleSet")] public int SupplierID; //驗証SupplierID變數的內容必須是介於1~100的數字 [RangeValidator(0, RangeBoundaryType.Inclusive, 100, RangeBoundaryType.Inclusive, MessageTemplate = "CategoryID必須是介於1~100的數字", Ruleset = "AttributeRuleSet")] public int CategoryID; //驗証CategoryID變數的內容必須是介於1~100的數字 [StringLengthValidator(1, 20, MessageTemplate = "QuantityPerUnit的長度必須是介於1~4個字元的字串", Ruleset = "AttributeRuleSet")] public string QuantityPerUnit; //驗証"QuantityPerUnit變數內容的長度必須是介於1~4個字元的字串 [NotNullValidator(MessageTemplate="UnitPrice必須有內容值", Ruleset = "AttributeRuleSet")] public decimal UnitPrice; //驗証UnitPrice變數必須有內容值 [RangeValidator(0, RangeBoundaryType.Inclusive, 100, RangeBoundaryType.Inclusive, MessageTemplate = "UnitsInStock必須是介於1~100的數字", Ruleset = "AttributeRuleSet")] public int UnitsInStock; //驗証UnitsInStock變數的內容必須是介於1~100的數字 [RangeValidator(0, RangeBoundaryType.Inclusive, 100, RangeBoundaryType.Inclusive, MessageTemplate = " UnitsOnOrder必須是介於1~100的數字", Ruleset = "AttributeRuleSet")] public int UnitsOnOrder; //驗証UnitsOnOrder變數的內容必須是介於1~100的數字 [RangeValidator(0, RangeBoundaryType.Inclusive, 100, RangeBoundaryType.Inclusive, MessageTemplate = "ReorderLevel必須是介於1~100的數字", Ruleset = "AttributeRuleSet")] public int ReorderLevel; //驗証ReorderLevel變數的內容必須是介於1~100的數字 [NotNullValidator(MessageTemplate="Discontinued必須有內容值", Ruleset = "AttributeRuleSet")] public bool Discontinued; //驗証Discontinued變數必須有內容值 } ================ ============= 程式2 string strConn = "Data Source=.;Initial Catalog=Northwind;Integrated Security=True"; //資料庫連線資訊 public ValidateAttributeProduct GetProduct(int ProductID, ref string strError) { string strSQL = "Select * from Products where ProductID=@ProductID"; //查詢商品資訊的SQL敘述 SqlConnection conn = new SqlConnection(strConn); //建立SqlConnection類別的物件 SqlCommand cmd = new SqlCommand(strSQL, conn); //建立SqlCommand類別的物件 cmd.CommandType = CommandType.Text; //設定SqlCommand類別的物件的CommandType屬性 cmd.Parameters.AddWithValue("@ProductID", ProductID); //設定@ProductID參數的內容值 conn.Open(); //開啟資料庫連線 SqlDataReader dr = cmd.ExecuteReader();//呼叫SqlCommand類別的ExecuteReader方法對資料庫執行查詢 dr.Read(); //讀取查詢得到的第一筆記錄 ValidateAttributeProduct p = new ValidateAttributeProduct(); //建立ValidateAttributeProduct類別的物件 p.ProductID = int.Parse(dr["ProductID"].ToString()); //設定物件的ProductID屬性的內容值 p.ProductName = dr["ProductName"].ToString(); //設定物件的ProductName屬性的內容值 p.SupplierID = int.Parse(dr["SupplierID"].ToString()); //設定物件的SupplierID屬性的內容值 p.CategoryID = int.Parse(dr["CategoryID"].ToString()); //設定物件的CategoryID屬性的內容值 p.QuantityPerUnit = dr["QuantityPerUnit"].ToString(); //設定物件的QuantityPerUnit屬性的內容值 p.UnitPrice = decimal.Parse(dr["UnitPrice"].ToString()); //設定物件的UnitPrice屬性的內容值 p.UnitsInStock = Int16.Parse(dr["UnitsInStock"].ToString()); //設定物件的UnitsInStock屬性的內容值 p.UnitsOnOrder = Int16.Parse(dr["UnitsOnOrder"].ToString());//設定物件的UnitsOnOrder屬性的內容值 p.ReorderLevel = Int16.Parse(dr["ReorderLevel"].ToString()); //設定物件的ReorderLevel屬性的內容值 p.Discontinued = bool.Parse(dr["Discontinued"].ToString()); //設定物件的Discontinued屬性的內容值 dr.Close(); //關閉SqlDataReader類別的物件 dr.Dispose(); //丟棄SqlDataReader類別的物件 cmd.Dispose(); //丟棄SqlCommand類別的物件 conn.Close(); //關閉資料庫連線 conn.Dispose(); //丟棄SqlCoonnection類別的物件 Validator validator=ValidationFactory.CreateValidator ("AttributeRuleSet"); //建立可以依據名稱為AttributeRuleSet的驗証規則集合進 //行資料驗証的Validator物件 ValidationResults results = validator.Validate(p); //呼叫Validator類別的Validate方法驗証 //ValidateAttributeProduct類別的物件的內容是否正確 if (results.IsValid) //如果資料驗証成功 { strError = "查詢成功!"; //顯示資料驗証成功的訊息 return p; //傳回ValidateAttributeProduct類別的物件 } else { StringBuilder sb = new StringBuilder(); //建立存放驗証錯誤的訊息的StringBuilder物件 foreach (ValidationResult result in results) //取出每一個錯誤訊息 { sb.Append(String.Format("- {0}:{1}
", "ProductName", result.Message)); //設定錯誤訊息的顯示格式 } strError = sb.ToString(); //顯示錯誤訊息 return null; //傳回null } } ================ ============= 程式3 Validator ProductNameValidator = new AndCompositeValidator( //建立組合兩個Validator的 new NotNullValidator(), //AndCompositeValidator類別的物件 new StringLengthValidator(1, 5)); ValidationResults r = Validation.Validate(p.ProductName); //驗証p的ProductName變數的內容是否正確 ================ ============= 程式4 [HasSelfValidation] //標示為擁有自我測試功能的類別 public class SelfValidateProduct { public int ProductID; public string ProductName; public int SupplierID; public int CategoryID; public string QuantityPerUnit; public decimal UnitPrice; public int UnitsInStock; public int UnitsOnOrder; public int ReorderLevel; public bool Discontinued; [SelfValidation] //負責執行自我測試的方法 public void DoValidate(ValidationResults results) { if (string.IsNullOrEmpty(ProductName)) //如果ProductName變數沒有內容值 { results.AddResult(new ValidationResult("ProductName不可空白!", this, "ProductName", null, null)); //填入新的錯誤訊息到名稱為results的參數中 } } } ================ ============= 程式5 protected void btnSelfValidate_Click(object sender, EventArgs e) { SelfValidateProduct p = new SelfValidateProduct(); //建立SelfValidateProduct類別的物件 p.ProductName = txtProductName.Text; //設定物件的ProductName變數的內容 p.SupplierID = int.Parse(txtSupplierID.Text); //設定物件的SupplierID變數的內容 p.CategoryID = int.Parse(txtCategoryID.Text); //設定物件的CategoryID變數的內容 p.QuantityPerUnit = txtQuantityPerUnit.Text; //設定物件的QuantityPerUnit變數的內容 p.UnitPrice = decimal.Parse(txtUnitPrice.Text); //設定物件的UnitPrice變數的內容 p.UnitsInStock = Int16.Parse(txtUnitsInStock.Text); //設定物件的UnitsInStock變數的內容 p.UnitsOnOrder = Int16.Parse(txtUnitsOnOrder.Text); //設定物件的UnitsOnOrder變數的內容 p.ReorderLevel = Int16.Parse(txtReorderLevel.Text); //設定物件的ReorderLevel變數的內容 p.Discontinued = (txtDiscontinued.Text.Equals("True") ? true : false); //設定物件的Discontinued變數的內容 ValidationResults results = Validation.Validate(p); //呼叫Validation類別的Validate方法 //命令SelfValidateProduct類別的物件p進行自我驗証 if (results.IsValid) //如果驗証成功 { lbMessage.Text="驗証成功!"; //顯示驗証成功的訊息 } else //否則 { StringBuilder sb = new StringBuilder(); //建立StringBuilder類別的物件 foreach (ValidationResult result in results) //取出所有的驗証錯誤訊息 { sb.Append(String.Format("- {0}:{1}
", result.Key, result.Message)); //將錯誤訊息加入到StringBuilder類別的物件中 } lbMessage.Text = sb.ToString(); //顯示所有的錯誤訊息 } } ================ ============= 程式6 namespace DataAccess { class ASPNETIntegratedProduct { private int m_ProductName; //存放ProductName屬性的內容值 [StringLengthValidator(1, 5, MessageTemplate = "ProductName的長度必須是介於1~5個字元的字串", Ruleset = "IntegratedRuleset")] //設定ProductName屬性的資料驗証規則 public int ProductName //ProductName屬性 { get { return m_ProductName; } //取用ProductName屬性的函式 set { m_ProductName = value; } //設定ProductName屬性的函式 } } } ================ ============= 程式7 protected void PropertyProxyValidator1_ValueConvert(object sender, Microsoft.Practices.EnterpriseLibrary.Validation.Integration.ValueConvertEventArgs e) { e.ConvertedValue = e.ValueToConvert.ToString(); //轉型成字串之後填回e的參數的ValueToConvert屬性 } ================ ==<灰>=========== using System.Collections.Generic; using Microsoft.Practices.EnterpriseLibrary.Validation.Validators; using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; using Microsoft.Practices.EnterpriseLibrary.Validation.Configuration; ================ ============= 程式8 [ConfigurationElementType(typeof(CustomValidatorData))] //加上ConfigurationElementType Attribute設定 public class GenderValidator : DomainValidator //設定類別要繼承自DomainValidator類別 { private static List CorrectContent= new List(new string[] { "男", "女", "Male", "Female"}); //指定可以接受的內容值 public GenderValidator() : base(CorrectContent) //將可以接受的內容值傳遞給父類別 { } protected override string DefaultNonNegatedMessageTemplate //override名稱為//DefaultNonNegatedMessageTemplate //的屬性 { get { return "資料的內容並非性別合法的內容值"; } //傳回資料驗証失敗欲顯示的錯誤訊息 } } ================ ==<灰>=========== using Microsoft.Practices.EnterpriseLibrary.Validation.Validators; using Microsoft.Practices.EnterpriseLibrary.Validation; ================ 再製作一個繼承自ValidatorAttribute類別的子類別,並將類別編輯成程式9。之後就可以為類別加入驗証性別資料的內容是否正確的功能了。例如程式10的Employee類別就會利用上述的GenderValidatorAttribute類別驗証名稱為Gender的屬性是否具有合法的內容值。 ============= 程式9 public class GenderValidatorAttribute : ValidatorAttribute /設定類別要繼承自ValidatorAttribute類別 { protected override Validator DoCreateValidator(Type targetType) //override DoCreateValidator方法 { return new GenderValidator(); //建立負責執行資料驗証動作的GenderValidator類別 } } ================ ============= 程式10 public class Employee { private string m_Gender; //存放Gender屬性內容值的變數 [GenderValidator(MessageTemplate="不合法的性別內容", Ruleset="GenderRule")] //指定使用GenderValidator驗証屬性並將資料名稱設定為GenderRule public string Gender //存放性別資訊的屬性 { get { return m_Gender; } //傳回性別的內容值 set { m_Gender = value; } //設定性別的內容值 } } ================ ============= 程式11 protected void btnSubmit_Click(object sender, EventArgs e) { Employee emp = new Employee(); //建立Employee類別的物件 emp.Gender = txtGender.Text; //填入使用者輸入的性別資訊 ValidationResults vr=Validation.Validate(emp, "GenderRule"); //建立驗証Employee類別的物件內容的Validator,指定要使用名稱為 //GenderRule的驗証規則集合進行資料驗証的動作 if (vr.IsValid) //如果資料驗証無誤 { lbMessage.Text="資料驗証成功!"; //顯示資料驗証成功的訊息 } else { StringBuilder sb = new StringBuilder(); //建立StringBuilder類別的物件 foreach (ValidationResult result in vr) //取出驗証失敗的每一個錯誤訊息 { sb.Append(String.Format("- {0}:{1}
", "Gender", result.Message)); //將錯誤訊息加入到StringBuilder類別的物件中 } lbMessage.Text = sb.ToString(); //將錯誤訊息顯示在網頁上 } } ================