簡體   English   中英

驗證C#中的列表

[英]Validating lists in C#

我們正在使用DataAnnotations來驗證我們的模型。

我們模型的一個非常簡化的版本是:

public class Model
{
    public List<Thing> Things;
}

public class Thing
{
    [Required]
    public string Name {get;set;}
}

現在,有趣的是,如果我創建一個沒有名稱的Thing並將其添加到模型中,我希望驗證會失敗,但是驗證會通過(震驚!)。

var model = new Model ();
var invalidThing = new Thing (); // No name would fail validation
model.Things.Add(invalidThing );

var validationContext = new ValidationContext(model);
var validationResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(model, validationContext, validationResults, true);

Assert.False (isValid);  // This fails!

認為這樣做的原因是,當您驗證模型時,它會驗證每個屬性,但會驗證屬性中的項目(如果是集合)。 Things是沒有驗證的屬性,因此它可以通過(盡管它包含無效項)。

我們如何確保驗證也可以驗證集合屬性中的項目? 我可以使用一些現成的驗證器嗎?

我已經通過為集合創建一個自定義驗證器來解決此問題,該集合用於檢查每個項目的驗證。 簡化的代碼如下所示:

public class ValidateEachItemAttribute : ValidationAttribute
{
    protected readonly List<ValidationResult> validationResults = new List<ValidationResult>();

    public override bool IsValid(object value)
    {
        var list = value as IEnumerable;
        if (list == null) return true;

        var isValid = true;

        foreach (var item in list)
        {
            var validationContext = new ValidationContext(item);
            var isItemValid = Validator.TryValidateObject(item, validationContext, validationResults, true);
            isValid &= isItemValid;
        }
        return isValid;
    }

    // I have ommitted error message formatting
}

現在以這種方式裝飾模型將按預期工作:

public class Model
{
    [ValidateEachItem]
    public List<Thing> Things;
}

如果這是ASP.NET MVC ,則另一種選擇是在模型中實現IValidatableObject 喜歡:

public class Model: IValidatableObject
{
    public List<Thing> Things;

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
       //your validation logic here
    }
}

然后, controllerModelState.IsValid的結果將取決於Validate方法的實現。 當模型的多個屬性相互依賴時,這很有用。

您問題中的默認行為不足為奇,下面將對其進行描述。 假設您有一個Dictionary<string, Thing>類型的屬性或Something<Thing>類型的屬性或Model包含Thing對象的無類型集合,那么我們如何期望Validator對存儲的Thing對象執行驗證在那些屬性?

我們不能期望Validator對存儲在這些屬性中的Thing對象執行驗證,因為它沒有有關如何驗證那些屬性的任何信息。 為了驗證屬性, Validator為該屬性尋找ValidationAttribute ,並且由於找不到任何驗證屬性,因此不會驗證該屬性。

結果,您需要創建一些ValidationAttribute來為您執行此操作,並用驗證屬性裝飾屬性。 您可以實現與答案中類似的內容。

注意:在ASP.NET MVC的上下文中,您不必擔心它。 當模型綁定時,即使模型綁定到列表,默認模型綁定器也會照顧所有驗證屬性。

這是默認模型聯編程序的工作。 在創建每個元素時,在為屬性分配值時,它會驗證屬性並將驗證錯誤添加到模型狀態。 最后,所有屬性和對象都經過驗證,並且模型狀態包含所有驗證錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM