我在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.
天啊。我忘了宣布属性而不是字段。
答案 0 :(得分:7)
有两种方法可以设置词典值的验证。如果您不关心获取所有错误,只是遇到第一个错误,您可以使用自定义验证属性。
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;
}
}
答案 1 :(得分:1)
验证始终传递字段,因为属性只能应用于属性。您需要使用自动实现的getter和setter将字段名称和desc更改为属性。
这些应该看起来像
public string name { get; set; }