2010-02-13 83 views
4

從我的經驗很多的驗證框架,.NET允許你在一個時間做這樣的事情,確保現場驗證單場之間做編輯是一個郵政編碼或電子郵件地址的實例。我通常稱這些是現場編輯。驗證框架在.NET中可以場

在我的項目,我們經常有,雖然現場編輯間的事。舉例來說,如果你有一個這樣的類:

public class Range 
{ 
    public int Min { get; set; } 
    public int Max { get; set; } 
} 

您可能希望確保最大大於MIN。您可能還想對外部對象進行一些驗證。比如給你有一個這樣的類:

public class Person 
{ 
    public string PostalCode { get; set; } 
} 

以任何理由要保證郵政編碼存在於數據庫或提供給您的文件。我有更復雜的例子,例如用戶提供數據字典的位置,以及要根據數據字典驗證對象的情況。

我的問題是:我們可以使用任何現有的驗證框架(TNValidate,NHibernate的驗證)for .NET的還是我們需要使用規則引擎還是什麼?現實世界中的人們如何處理這種情況? :-)

回答

6

這裏只有一個解決框架,我清楚地知道,這是Enterprise Library Validation Application Block,或VAB的簡稱。我會從VAB的背景下回答你的問題。

第一個問題:在VAB你能做到狀態之間(場)驗證?

是的,你可以。有多種方法可以做到這一點。您可以選擇自我驗證機制,方法如下:

[HasSelfValidation] 
public class Range 
{ 
    public int Min { get; set; } 
    public int Max { get; set; } 

    [SelfValidation] 
    public void ValidateRange(ValidationResults results) 
    { 
     if (this.Max < this.Min) 
     { 
      results.AddResult(
       new ValidationResult("Max less than min", this, "", "", null)); 
     } 
    } 
} 

我必須說,我親自驗證我的域實體尤其是當不喜歡這種類型的驗證的,因爲我喜歡讓我驗證從分離驗證邏輯(並保持我的域邏輯免於引用任何驗證框架)。但是,他們需要比替代方法少得多的代碼,而替代方法是編寫自定義驗證器類。這裏有一個例子:

[ConfigurationElementType(typeof(CustomValidatorData))] 
public sealed class RangeValidator : Validator 
{ 
    public RangeValidator(NameValueCollection attributes) 
     : base(string.Empty, string.Empty) { } 

    protected override string DefaultMessageTemplate 
    { 
     get { throw new NotImplementedException(); } 
    } 

    protected override void DoValidate(object objectToValidate, 
     object currentTarget, string key, ValidationResults results) 
    { 
     Range range = (Range)currentTarget; 

     if (range.Max < range.Min) 
     { 
      this.LogValidationResult(results, 
       "Max less than min", currentTarget, key); 
     } 
    } 
} 

寫這個類,你可以在你的驗證配置文件中像這樣勾該類完畢後:

<validation> 
    <type name="Range" defaultRuleset="Default" assemblyName="[Range Assembly]"> 
    <ruleset name="Default"> 
     <validator type="[Namespace].RangeValidator, [Validator Assembly]" 
     name="Range Validator" /> 
    </ruleset> 
    </type> 
</validation> 

第二個問題:如何做複雜的驗證與可能的相互作用數據庫(與VAB)。

我給第一個問題的例子也適用於此。您可以使用相同的技術:自我驗證和自定義驗證器。您想要在數據庫中檢查值的場景實際上很簡單,因爲對象的有效性不基於其上下文。您可以簡單地根據數據庫檢查對象的狀態。當對象所處的上下文變得重要時(但VAB可能),它變得更加複雜。想象一下,例如,你想寫一個驗證,確保每個客戶在給定的時間,有不超過兩個未發貨的訂單。這不僅意味着您必須檢查數據庫,但可能在相同的上下文中刪除了添加的新訂單或訂單。這個問題不是VAB特定的,你會在你選擇的每一個框架上遇到同樣的問題。我寫了an article,描述了我們在這些情況下所面臨的複雜性(閱讀和顫抖)。

第三個問題:現實世界中的人們如何處理這種情況?

我在生產代碼中使用VAB進行這些類型的驗證。它工作得很好,但VAB並不是很容易學習。儘管如此,我喜歡用VAB做什麼,只有v5.0出來時它纔會變得更好。當您想要了解它時,首先閱讀可在Hands-On Labs下載中找到的ValidationHOL.pdf文檔。

我希望這會有所幫助。

0

我構建自定義驗證控件,當我需要的是不是包括開箱東西。這裏的好處是這些自定義驗證器是可重用的,他們可以在多個領域進行操作。下面是我張貼到CodeProject的AtLeastOneOf驗證器,讓你需要的是一組中至少一個字段的值的例子:

http://www.codeproject.com/KB/validation/AtLeastOneOfValidator.aspx

包含在下載的代碼應該工作作爲一個易於遵循樣本你如何去做。這裏的缺點是ASP.Net中包含的Validation控件通常不能很好地處理asp.net-ajax。

+0

如果您使用自定義驗證器,您可以重新使用後端中的代碼來驗證數據是可信的和正確的值等等,如果有人試圖攻擊您的網站而根本不使用前端。 – bristows 2010-02-13 18:18:30

+0

您可以在後端重新使用該代碼,但必須小心。在編寫可在多種產品中重複使用的驗證器控件和編寫驗證器控件(在多層應用程序中的多個層上重新使用代碼)之間往往有一定的折衷。 – 2010-02-13 21:02:01