是否可以将[Required]属性放入List<>属性?
我绑定到POST上的通用列表,并且想知道如果属性中有0项,我是否可以使ModelState.IsValid()失败?
答案 0 :(得分:30)
将Required
属性添加到list-style属性并不能真正做到你想要的。如果列表未创建,则会抱怨,但如果列表中存在0项,则不会抱怨。
但是,导出您自己的数据注释属性并使其检查Count
>的列表应该很容易。 0.这样的事情(尚未测试):
[AttributeUsage(AttributeTargets.Property)]
public sealed class CannotBeEmptyAttribute : ValidationAttribute
{
private const string defaultError = "'{0}' must have at least one element.";
public CannotBeEmptyAttribute ( ) : base(defaultError) //
{
}
public override bool IsValid ( object value )
{
IList list = value as IList;
return ( list != null && list.Count > 0 );
}
public override string FormatErrorMessage ( string name )
{
return String.Format(this.ErrorMessageString, name);
}
}
编辑:
您还必须小心如何在视图中绑定列表。例如,如果将List<String>
绑定到这样的视图:
<input name="ListName[0]" type="text" />
<input name="ListName[1]" type="text" />
<input name="ListName[2]" type="text" />
<input name="ListName[3]" type="text" />
<input name="ListName[4]" type="text" />
MVC模型绑定器始终在列表中放置5个元素,全部为String.Empty
。如果这是View的工作方式,那么您的属性需要更复杂,例如使用Reflection来提取泛型类型参数并将每个列表元素与default(T)
或其他内容进行比较。
更好的选择是使用jQuery动态创建输入元素。
答案 1 :(得分:23)
对于那些寻找极简主义例子的人:
[AttributeUsage(AttributeTargets.Property)]
public sealed class CannotBeEmptyAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
var list = value as IEnumerable;
return list != null && list.GetEnumerator().MoveNext();
}
}
这是已接受答案的修改代码。它适用于问题的情况,在更多情况下,因为IEnumerable在System.Collections层次结构中更高。此外,它继承了RequiredAttribute的行为,因此无需明确编码。
答案 2 :(得分:4)
对于那些使用C#6.0(及以上)并且正在寻找单行的人:
[AttributeUsage(AttributeTargets.Property)]
public sealed class CannotBeEmptyAttribute : RequiredAttribute
{
public override bool IsValid(object value) => (value as IEnumerable)?.GetEnumerator().MoveNext() ?? false;
}
答案 3 :(得分:2)
根据我的要求修改了@moudrick实现
列表和复选框列表
所需的验证属性[AttributeUsage(AttributeTargets.Property)]
public sealed class CustomListRequiredAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
var list = value as IEnumerable;
return list != null && list.GetEnumerator().MoveNext();
}
}
如果您有复选框列表
[AttributeUsage(AttributeTargets.Property)]
public sealed class CustomCheckBoxListRequiredAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
bool result = false;
var list = value as IEnumerable<CheckBoxViewModel>;
if (list != null && list.GetEnumerator().MoveNext())
{
foreach (var item in list)
{
if (item.Checked)
{
result = true;
break;
}
}
}
return result;
}
}
这是我的视图模型
public class CheckBoxViewModel
{
public string Name { get; set; }
public bool Checked { get; set; }
}
用法
[CustomListRequiredAttribute(ErrorMessage = "Required.")]
public IEnumerable<YourClass> YourClassList { get; set; }
[CustomCheckBoxListRequiredAttribute(ErrorMessage = "Required.")]
public IEnumerable<CheckBoxViewModel> CheckBoxRequiredList { get; set; }