ASP.NET 列表的 MVC 自定义验证<string>

ASP.NET MVC Custom validation for a List<string>

我正在使用 ASP.NET MVC 5,并且在客户端想要使用 JQuery 非侵入式验证。

以下是我的模型:

 public class CompanyModel
    {
        public CompanyModel()
        {
            Employees = new List<EmployeeModel>();              
        }
        public int CompanyId{ get; set; }

        public List<EmployeeModel> Employees { get; set; }        
    }

    public class EmployeeModel
    {
        public EmployeeModel()
        {
            Values = new List<string>();
        }

        public string Id { get; set; }

        public string Name { get; set; }

        [RequiredIf("IsRequired", true, "Atleast one value is required")]
        public List<string> Values { get; set; }

        public bool IsRequired { get; set; }
    }

我能够在服务器端成功实现 RequiredIf 自定义属性。但我正在努力让客户端验证继续进行......

在视图中循环遍历员工列表并绑定值集合

@for (var index = 0; index < Model.Employees.Count; index++)
{
      /// some other code

    @for (int i = 0; i < Model.employees[index].Values.Count; i++)
    {
        @Html.TextBoxFor(m => m.Employees[index].Values[i], new {@autocomplete = "false" })
    }    
 }

IsRequired 属性 是一个隐藏字段:

@Html.HiddenFor(m => m.Employees[index].IsRequired)

以下是我目前拥有的 GetClientValidationRules 方法代码。

  public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
            {
                var rule = new ModelClientValidationRule
                {
                    ErrorMessage = ErrorMessage,
                    ValidationType = "requiredif"
                };               

                rule.ValidationParameters["dependentproperty"] = (context as ViewContext).ViewData.TemplateInfo.GetFullHtmlFieldId(DependentProperty);
                rule.ValidationParameters["dependentpropertyvalue"] = DependentPropertyValue.ToString().ToLower();

                yield return rule;            
            }

我没有看到添加到 HTML 标记中的值的验证 html (data-val-*) 属性。而且我也不期望他们,因为我认为我错过了一些东西。如何获取在 html.

中填充了 data-val-requiredif 属性的值集合的所有元素

有什么想法吗?

仅供参考:html 中的相关 属性Id 像这样填充 CompanyModel。Employees_0_IsRequired for Employee[0]。

Required 验证仅确保 属性 具有值。在类似 List<string> 的情况下,这仅意味着它不为空。一个空列表仍然是一个列表,因此它可以很好地通过验证。实际上,您正在使用 RequiredIf,并且没有提供该自定义属性的实现,但我认为它依赖于基础 Required 属性,因为我见过的几乎所有实现都.

总而言之,您需要修改 RequiredIf 实现以考虑列表的内容和其他可枚举属性,或者您需要添加一些手动验证来检查列表是否确实至少有一项。

在您的验证属性中包含 GetClientValidationRules() 方法没有什么意义,因为它的目的是将 data-val-* 属性添加到为该 属性 生成的表单控件中,而您不要为 属性 Values 生成输入(如果这样做,绑定将失败)。解决这个问题的一种方法是处理表单 .submit() 事件,检查集合中是否至少有一个项目有值,如果没有则取消提交并显示错误。

修改您的视图以包含验证消息占位符并向输入添加 class 名称以供选择

@for (var index = 0; index < Model.Employees.Count; index++)
{
    ....
    <div class="value-group"> // necessary for relative selectors
        @for (int i = 0; i < Model.employees[index].Values.Count; i++)
        {
            @Html.TextBoxFor(m => m.Employees[index].Values[i], new { @class="value", autocomplete = "false" })
        }
        @Html.ValidationMessageFor(m => m.Employees[index].Values)
   </div>
}

并包含以下脚本

$('form').submit(function() { // use an id selector if you have added one to the form
    var isValid = true;
    var groups = $('.value-group');
    $.each(groups, function(index, item) {
        var group = $(this);
        var inputs = group.find('.value');
        if (inputs.filter(function () { return $(this).val().length > 0; }).length == 0) {
            isValid = false;
            group.find('span:last').append($('<span></span>').text('At least one value is required')).addClass('field-validation-error').removeClass('field-validation-valid');
        }
    });
    return isValid;
});

您可能还想添加另一个脚本来处理每个输入的更改事件,以便在组中的任何输入现在具有值时删除关联的错误消息