2013-10-18 184 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; }