List的ViewModel验证

rya*_*yan 71 c# asp.net model-validation fluentvalidation asp.net-mvc-3

我有以下viewmodel定义

public class AccessRequestViewModel
{
    public Request Request { get; private set; }
    public SelectList Buildings { get; private set; }
    public List<Person> Persons { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

所以在我的应用程序中,访问请求必须至少有一个人.您可以使用什么方法进行验证?我不希望在我的控制器中进行这种验证,这很简单.是自定义验证属性的唯一选择吗?

编辑:目前正在使用FluentValidation执行此验证(漂亮的库!)

RuleFor(vm => vm.Persons)
                .Must((vm, person) => person.Count > 0)
                .WithMessage("At least one person is required");
Run Code Online (Sandbox Code Playgroud)

Dar*_*rov 157

如果您使用数据批注来执行验证,则可能需要自定义属性:

public class EnsureOneElementAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        var list = value as IList;
        if (list != null)
        {
            return list.Count > 0;
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

[EnsureOneElement(ErrorMessage = "At least a person is required")]
public List<Person> Persons { get; private set; }
Run Code Online (Sandbox Code Playgroud)

或使其更通用:

public class EnsureMinimumElementsAttribute : ValidationAttribute
{
    private readonly int _minElements;
    public EnsureMinimumElementsAttribute(int minElements)
    {
        _minElements = minElements;
    }

    public override bool IsValid(object value)
    {
        var list = value as IList;
        if (list != null)
        {
            return list.Count >= _minElements;
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

[EnsureMinimumElements(1, ErrorMessage = "At least a person is required")]
public List<Person> Persons { get; private set; }
Run Code Online (Sandbox Code Playgroud)

我个人使用FluentValidation.NET而不是Data Annotations来执行验证,因为我更喜欢命令式验证逻辑而不是声明性.我认为它更强大.所以我的验证规则看起来像这样:

RuleFor(x => x.Persons)
    .Must(x => x.Count > 0)
    .WithMessage("At least a person is required");
Run Code Online (Sandbox Code Playgroud)


Sud*_*hir 14

处理视图模型对象的集合成员的计数验证的另一种可能方法是使计算属性返回集合或列表计数.然后可以像下面的代码一样应用RangeAttribute来强制执行计数验证:

[Range(minimum: 1, maximum: Int32.MaxValue, ErrorMessage = "At least one item needs to be selected")]
public int ItemCount
{
    get
    {
        return Items != null ? Items.Length : 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,ItemCount是要验证的视图模型上的示例计算属性,而Items是正在检查其计数的示例成员集合属性.在此示例中,在集合成员上强制执行至少一个项目,并且最大限制是整数可以采用的最大值,对于大多数实际目的而言,这是无限制的.验证失败的错误消息也可以通过上面示例中的RangeAttribute的ErrorMessage成员设置.


rah*_*han 8

以下代码在asp.net core 1.1中有效。

[Required, MinLength(1, ErrorMessage = "At least one item required in work order")]
public ICollection<WorkOrderItem> Items { get; set; }
Run Code Online (Sandbox Code Playgroud)

  • 这在.Net Core 2.2中有效,我已经在List类型上进行了尝试。如果您想为[Required]属性使用单独的自定义消息,也可以这样做。[Required(ErrorMessage =“ Missing Meters”),MinLength(1,ErrorMessage =“需要至少1米”)] public List &lt;Meter&gt; Meters {get; 组; } (2认同)

Sam*_*les 5

Darin的回答很好,但以下版本会自动为您提供有用的错误消息。

public class MinimumElementsAttribute : ValidationAttribute
{
    private readonly int minElements;

    public MinimumElementsAttribute(int minElements)
    {
        this.minElements = minElements;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var list = value as IList;

        var result = list?.Count >= minElements;

        return result
            ? ValidationResult.Success
            : new ValidationResult($"{validationContext.DisplayName} requires at least {minElements} element" + (minElements > 1 ? "s" : string.Empty));
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

[MinimumElements(1)]
public List<Customer> Customers {get;set}

[MinimumElements(2)]
public List<Address> Addresses {get;set}
Run Code Online (Sandbox Code Playgroud)

错误信息:

  • 客户需要至少1个元素
  • 地址至少需要2个元素