一个列表的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; }