如果我有一个包含字段列表的搜索对象,我是否可以使用System.ComponentModel.DataAnnotations命名空间将其设置为验证搜索中至少有一个字段不为空或为空?即所有字段都是可选字段,但至少应输入一个字段。
答案 0 :(得分:22)
我会为此创建一个自定义验证器 - 它不会给你客户端验证,只是服务器端。
请注意,为了实现此目的,您需要使用nullable
类型,因为值类型默认为0
或false
:
首先创建一个新的验证器:
using System.ComponentModel.DataAnnotations;
using System.Reflection;
// This is a class-level attribute, doesn't make sense at the property level
[AttributeUsage(AttributeTargets.Class)]
public class AtLeastOnePropertyAttribute : ValidationAttribute
{
// Have to override IsValid
public override bool IsValid(object value)
{
// Need to use reflection to get properties of "value"...
var typeInfo = value.GetType();
var propertyInfo = typeInfo.GetProperties();
foreach (var property in propertyInfo)
{
if (null != property.GetValue(value, null))
{
// We've found a property with a value
return true;
}
}
// All properties were null.
return false;
}
}
然后你可以用这个装饰你的模型:
[AtLeastOneProperty(ErrorMessage="You must supply at least one value")]
public class SimpleTest
{
public string StringProp { get; set; }
public int? Id { get; set; }
public bool? BoolProp { get; set; }
}
然后,当您致电ModelState.IsValid
时,系统会调用您的验证工具,您的信息将被添加到您视图的ValidationSummary中。
请注意,您可以对此进行扩展以检查返回的属性类型,或者如果您愿意,可以在其上查找属性以包含/排除验证 - 这假设一个通用验证器不知道任何有关输入它验证。
答案 1 :(得分:22)
我已经扩展了Zhaph的答案以支持属性分组。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AtLeastOnePropertyAttribute : ValidationAttribute
{
private string[] PropertyList { get; set; }
public AtLeastOnePropertyAttribute(params string[] propertyList)
{
this.PropertyList = propertyList;
}
//See http://stackoverflow.com/a/1365669
public override object TypeId
{
get
{
return this;
}
}
public override bool IsValid(object value)
{
PropertyInfo propertyInfo;
foreach (string propertyName in PropertyList)
{
propertyInfo = value.GetType().GetProperty(propertyName);
if (propertyInfo != null && propertyInfo.GetValue(value, null) != null)
{
return true;
}
}
return false;
}
}
用法:
[AtLeastOneProperty("StringProp", "Id", "BoolProp", ErrorMessage="You must supply at least one value")]
public class SimpleTest
{
public string StringProp { get; set; }
public int? Id { get; set; }
public bool? BoolProp { get; set; }
}
如果你想拥有2组(或更多):
[AtLeastOneProperty("StringProp", "Id", ErrorMessage="You must supply at least one value")]
[AtLeastOneProperty("BoolProp", "BoolPropNew", ErrorMessage="You must supply at least one value")]
public class SimpleTest
{
public string StringProp { get; set; }
public int? Id { get; set; }
public bool? BoolProp { get; set; }
public bool? BoolPropNew { get; set; }
}
答案 2 :(得分:1)
这个问题很老了,但是从.NET 3.5开始(我相信),IValidatableObject可以帮助解决棘手的验证问题。您可以实现它来验证任意业务规则。在这种情况下,例如:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(FieldOne) && string.IsNullOrWhiteSpace(FieldTwo))
yield return new ValidationResult("Must provide value for either FieldOne or FieldTwo.", new string[] { "FieldOne", "FieldTwo" });
}
答案 3 :(得分:0)
如果您想针对任何.Net类进行复杂的验证,而不需要使用注释,请查看FluentValidation或.Net 2.0,FluentValidation for 2.0