2013-10-18 84 views
3

我在asp.net web api的模型綁定和驗證(通過數據註釋)中遇到了一些問題。Asp.net Web Api嵌套模型驗證

好像如果我有一個模型與屬性,如

Dictionary<string, childObject> obj { get; set; } 

的childObject的驗證似乎並沒有觸發。數據從Json綁定到Json.Net序列化器。

有沒有一些解決方法或修復?還是我誤解了與此相關的其他內容?


我不禁想知道爲什麼這不會導致錯誤:

public class Child 
{   
    [Required] 
    [StringLength(10)] 
    public string name; 
    [Required] 
    [StringLength(10)] 
    public string desc;  
} 

//elsewhere 
Child foo = new Child(); 
foo.name = "hellowrodlasdasdaosdkasodasasdasdasd"; 

List<ValidationResult> results = new List<ValidationResult>(); 
Validator.TryValidateObject(foo, new ValidationContext(foo), results, true); 
// results.length == 0 here. 

天啊。我忘記了聲明屬性而不是字段。

回答

5

有兩種方法可以設置字典值的驗證。如果您不關心獲取所有錯誤,但僅僅遇到第一個錯誤,則可以使用自定義驗證屬性。

public class Foo 
{ 
    [Required] 
    public string RequiredProperty { get; set; } 

    [ValidateDictionary] 
    public Dictionary<string, Bar> BarInstance { get; set; } 
} 

public class Bar 
{ 
    [Required] 
    public string BarRequiredProperty { get; set; } 
} 

public class ValidateDictionaryAttribute : ValidationAttribute 
{ 
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     if (!IsDictionary(value)) return ValidationResult.Success; 

     var results = new List<ValidationResult>(); 
     var values = (IEnumerable)value.GetType().GetProperty("Values").GetValue(value, null); 
     values.OfType<object>().ToList().ForEach(item => Validator.TryValidateObject(item, new ValidationContext(item, null, validationContext.Items), results)); 
     Validator.TryValidateObject(value, new ValidationContext(value, null, validationContext.Items), results); 
     return results.FirstOrDefault() ?? ValidationResult.Success; 
    } 

    protected bool IsDictionary(object value) 
    { 
     if (value == null) return false; 
     var valueType = value.GetType(); 
     return valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof (Dictionary<,>); 
    } 
} 

另一種方法是創建自己的字典作爲IValidatableObject並在那做驗證。該解決方案使您能夠返回所有錯誤。

public class Foo 
{ 
    [Required] 
    public string RequiredProperty { get; set; } 

    public ValidatableDictionary<string, Bar> BarInstance { get; set; } 
} 

public class Bar 
{ 
    [Required] 
    public string BarRequiredProperty { get; set; } 
} 

public class ValidatableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IValidatableObject 
{ 
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     var results = new List<ValidationResult>(); 
     Values.ToList().ForEach(item => Validator.TryValidateObject(item, new ValidationContext(item, null, validationContext.Items), results)); 
     return results; 
    } 
} 
+0

對不起,我不能得到這個工作我自己。代碼看起來是合乎邏輯的,但都不適用於我...... ValidatableDictionary確實覆蓋了這些項目,但由於某種原因不會填充結果,即使我們在子項的屬性StringLength(5)的信件。我得看看這個更多... – Toni

+0

沒關係。我沒有將類屬性聲明爲屬性。衛生署。 – Toni

1

驗證始終傳遞字段,因爲屬性只能應用於屬性。您需要使用自動實現的getter和setter將字段名稱和desc更改爲屬性。

這些應該然後看起來像

public string name { get; set; }