在具有相同ID的下拉字段列表中,validation下拉项不会出现多次

我有一个表单,用户可以根据需要添加任意数量的行。 每次他们期望从提供的下拉列表中选择不同的选项。 目前没有validation可以阻止他们多次选择相同的值。

在此处输入图像描述

每行都是“ResourceCount”。 ViewModel具有IList的ResourceCountViewModel,因此每行都作为项添加到列表中。

ResourceCount视图模型包含用于存储所选下拉值的“id”和用于数字字段的“数量”。

我想不出在这种情况下使用比较注释的方法。 如何为此实施适当的validation?

编辑:在接受的答案中有很多好的建议。 我在控制器后期操作中进行了简单的检查:

if (resourceCounts.Count != resourceCounts.Where(d => d.Id!= 0) .Select(x => x.Id) .Distinct() .Count()) { ModelState.AddModelError(string.Empty, "You can't select the same option more than once"); //etc. } 

使用ValidationAttribute (内置或自定义)和MVC不显眼的客户端validation是不可能的。

validation属性应用于模型(您的类)的属性,并且检查validation的上下文仅适用于该实例 – 它不知道集合中模型的其他实例,因此无法比较其他实例。

相反,如果将ValidationAttribute应用于集合(例如List属性),则不显眼的validation将不起作用,因为只有在包含输入的情况下才能生成将规则添加到$.validator所需的data-val-*属性collection属性(与集合中每个对象的每个属性相对),这意味着ModelBinding将失败。

您需要编写自己的控制器代码和脚本来实现自定义validation。

在客户端,您可以处理.change()事件,并检查以前的选择是否匹配,如果是,则显示错误消息。 您尚未显示模型或视图,但基于以下html(对集合中的每个对象重复)

  

那么剧本就是

 var errors = $('.error'); var selects = $('.select'); $('.select').change(function() { var selected = $.map(selects, function(s, i) { return $(s).val(); }) $.each(selects, function(i, s) { var error = $(this).next('.error'); var val = $(this).val(); var index = i; if ($(this).val()) { var others = selected.filter(function(s, i) { if (i != index) { return s; } }); if (others.indexOf(val) > -1) { error.text('Please make a unique selection'); } else { error.text(''); } } else { error.text(''); } }) }) 

请参阅这个小提琴以获得一个工作示例。

或者,您可以隐藏/显示(或禁用)每个选项,以防止用户首先进行无效选择,但如果动态添加/删除项目和/或视图正在编辑现有项目,则会变得更加复杂该属性已经具有选定值的数据(如果您想要实现该属性,我将留给您询问显示您尝试的新问题)。

在服务器端,您可以检查重复值,如果是,则添加ModelState错误并返回视图,例如

 var selected = new List(); for (int i = 0 i < model.Count; i++) { if (selected.Contains(model[i].YourProperty)) { ModelState.AddModelError("", "Please make a unique selection"); break; } else { selected.Add(model[i].YourProperty); } } if (!ModelState.IsValid) { return View(model); } .... 

或使用linq

 if (model.Select(x => x.YourProperty).GroupBy(x => x).Any(g => g.Count() > 1)) { ModelState.AddModelError("", "Please make a unique selection"); } 

然后将显示在视图@Html.ValidationSummary()

如果你在每个下拉列表的视图中使用@Html.ValidationMessageFor(m => m[i].YourProperty) ,那么上面的循环可以修改为

 if (selected.Contains(model[i].YourProperty)) { var propertyName = string.Format("[{0}].yourPropertyName", i); ModelState.AddModelError(propertyName, "Please make a unique selection"); break; } 

并修改脚本以添加/删除由ValidationMessageFor()生成的元素的消息(即,而不是如上所示的

元素)

另外,如果您想了解有关validation属性如何与客户端validation相结合的更多信息,我建议您阅读ASP.NET MVC 3中的完整指南validation - 第2部分 。