[英]ViewModel validation for a List
我有以下视图模型定义
public class AccessRequestViewModel
{
public Request Request { get; private set; }
public SelectList Buildings { get; private set; }
public List<Person> Persons { get; private set; }
}
因此,在我的应用程序中,必须至少有1个人才能进行访问请求。 您可以使用哪种方法进行验证? 我不希望这种验证在我的控制器中发生,这很容易做到。 唯一选择是自定义验证属性吗?
编辑:当前与FluentValidation执行此验证(不错的库!)
RuleFor(vm => vm.Persons)
.Must((vm, person) => person.Count > 0)
.WithMessage("At least one person is required");
如果使用数据注释执行验证,则可能需要一个自定义属性:
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代替数据注释来执行验证,因为我更喜欢命令式验证逻辑而不是声明式逻辑。 我认为它更强大。 因此,我的验证规则将如下所示:
RuleFor(x => x.Persons)
.Must(x => x.Count > 0)
.WithMessage("At least a person is required");
处理视图模型对象的集合成员的计数验证的另一种可能方法是,使计算所得的属性返回集合或列表的计数。 然后可以像下面的代码中那样应用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;
}
}
在上面的代码中,ItemCount是正在验证的视图模型上的示例计算属性,而Items是正在检查其计数的示例成员集合属性。 在此示例中,对集合成员强制执行了至少一项,并且最大限制是整数可以采用的最大值,对于大多数实际目的而言,该最大值是无界的。 在上面的示例中,也可以通过RangeAttribute的ErrorMessage成员设置有关验证失败的错误消息。
以下代码在asp.net core 1.1中有效。
[Required, MinLength(1, ErrorMessage = "At least one item required in work order")]
public ICollection<WorkOrderItem> Items { get; set; }
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));
}
}
用法:
[MinimumElements(1)]
public List<Customer> Customers {get;set}
[MinimumElements(2)]
public List<Address> Addresses {get;set}
错误信息:
您在这里有两个选择,要么创建一个“自定义验证属性”并用它来装饰属性,要么可以使ViewModel实现IValidatableObject
接口(定义了Validate
方法)。
希望这可以帮助 :)
一种方法可能是使用私有构造函数和静态方法来返回对象的实例。
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,可以确保始终有一个人。
这可能不是您想要的理想选择,但可能会起作用。
进行自定义验证会非常干净优雅。 像这样:
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)]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.