一个列表的ViewModelvalidation

我有以下viewmodel定义

public class AccessRequestViewModel { public Request Request { get; private set; } public SelectList Buildings { get; private set; } public List<Person> Persons { get; private set; } } 

所以在我的应用程序中,至less有一个访问请求的人。 你可以用什么方法来validation? 我不希望在我的控制器中进行validation,这很容易实现。 是自定义validation属性的唯一select吗?

编辑:目前使用FluentValidation进行validation(很好的库!)

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

如果您使用数据注释来执行validation,则可能需要一个自定义属性:

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

接着:

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

或者使其更通用:

 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; } } 

接着:

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

我个人使用FluentValidation.NET而不是数据注解来执行validation,因为我更喜欢命令式validation逻辑而不是声明式。 我认为它更强大。 所以我的validation规则看起来像这样:

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

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

 [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; } } 

在上面的代码中,ItemCount是一个正在validation的视图模型的计算属性的示例,而Items是正在检查其计数的示例成员集合属性。 在这个例子中,集合成员至less执行一个项目,最大限制是整数可以取的最大值,这对大多数实际目的来说是无界的。 validation失败的错误信息也可以通过上面例子中的RangeAttribute的ErrorMessage成员来设置。

有一个自定义validation将是非常干净和优雅。 像这样的东西:

 public class AccessRequestViewModel { public Request Request { get; private set; } public SelectList Buildings { get; private set; } [AtLeastOneItem] public List<Person> Persons { get; private set; } } 

[MinimumItems(1)]

一种方法可能是使用私有构造函数和静态方法来返回对象的一个​​实例。

 public class AccessRequestViewModel { private AccessRequesetViewModel() { }; public static GetAccessRequestViewModel (List<Person> persons) { return new AccessRequestViewModel() { Persons = persons, }; } public Request Request { get; private set; } public SelectList Buildings { get; private set; } public List<Person> Persons { get; private set; } } 

通过始终使用工厂来实例化您的ViewModel,您可以确保始终有一个人。

这可能不是你想要的,但它可能会工作。

在这里你有两个select,要么创build一个自定义validation属性,并用它来装饰属性,或者你可以让你的ViewModel实现IValidatableObject接口(它定义了一个Validate方法)

希望这可以帮助 :)

以下代码在asp.net核心1.1中工作。

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