【发布时间】:2011-02-12 08:10:14
【问题描述】:
如果我有一个包含字段列表的搜索对象,我是否可以使用 System.ComponentModel.DataAnnotations 命名空间将其设置为验证搜索中的至少一个字段不为空或不为空?即所有字段都是可选的,但至少应始终输入一个。
【问题讨论】:
标签: asp.net asp.net-mvc validation asp.net-mvc-2 data-annotations
如果我有一个包含字段列表的搜索对象,我是否可以使用 System.ComponentModel.DataAnnotations 命名空间将其设置为验证搜索中的至少一个字段不为空或不为空?即所有字段都是可选的,但至少应始终输入一个。
【问题讨论】:
标签: asp.net asp.net-mvc validation asp.net-mvc-2 data-annotations
我已扩展 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; }
}
【讨论】:
我会为此创建一个自定义验证器 - 它不会为您提供客户端验证,只是服务器端。
请注意,要使其正常工作,您需要使用 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 中。
请注意,您可以扩展它以检查返回的属性类型,或者在它们上查找属性以在验证中包含/排除(如果您愿意) - 这是假设一个通用验证器对输入它正在验证。
【讨论】:
这个问题已经很老了,但是从 .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" });
}
【讨论】:
如果您想对任何 .Net 类进行复杂的验证,而不用注解,请查看 FluentValidation,或者对于 .Net 2.0,FluentValidation for 2.0
【讨论】:
.net 中的验证检查属性。假设您有两个字符串属性,field1 和 field2。只需添加这样的属性。
[RegularExpression("True|true", ErrorMessage = "At least one field must be given a value")]
public bool Any => field1 != null || field2 != null;
此处有详细信息,以及 MinLength 等附加验证:https://stackoverflow.com/a/69621414/6742644
【讨论】: