通用列表属性上的必需属性

Nic*_*eve 31 validation asp.net-mvc model generic-list

是否可以将[Required]属性放入List <>属性?

我绑定到POST上的通用列表,并想知道如果属性中有0项,我是否可以使ModelState.IsValid()失败?

Mic*_*eld 33

Required属性添加到列表样式属性并不能真正做到你想要的.如果列表未创建,则会抱怨,但如果列表中存在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

您还必须小心如何在视图中绑定列表.例如,如果将a绑定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" />
Run Code Online (Sandbox Code Playgroud)

MVC模型绑定器将始终在列表中放置5个元素String.Empty.如果这是View的工作方式,那么您的属性需要更复杂一些,例如使用Reflection来拉取泛型类型参数并将每个列表元素与default(T)某些内容进行比较.

更好的选择是使用jQuery动态创建输入元素.


mou*_*ick 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是已接受答案的修改代码.它适用于问题的情况,在更多情况下,因为IEnumerable在System.Collections层次结构中更高.此外,它继承了RequiredAttribute的行为,因此无需明确编码.

  • 一项改进是还调用“base.IsValid(value)”,以便维护基类行为。对于 C# 8 的用户,这可以像 `return base.IsValid(value) &amp;&amp; value is IEnumerable seq &amp;&amp; seq.GetEnumerator().MoveNext();` 一样简单 (3认同)

Nic*_* N. 5

对于那些使用 C# 6.0(及更高版本)并且正在寻找单行代码的人:

[AttributeUsage(AttributeTargets.Property)]
public sealed class CannotBeEmptyAttribute : RequiredAttribute
{
    public override bool IsValid(object value) => (value as IEnumerable)?.GetEnumerator().MoveNext() ?? false;
}
Run Code Online (Sandbox Code Playgroud)