用于List <string>的ASP.NET MVC自定义验证

时间:2016-03-07 17:17:38

标签: jquery asp.net-mvc asp.net-mvc-4 unobtrusive-validation

我正在使用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(data-val- *)属性添加到HTML标记中的值。而且我也不指望它们,因为我认为我错过了一些东西。如何在html中使用data-val-requiredif属性填充值集合的所有元素。

有什么想法吗?

仅供参考:html中的dependentpropertyId的填充方式与Employee [0]的CompanyModel.Employees_0_IsRequired类似。

2 个答案:

答案 0 :(得分:1)

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

修改视图以包含验证消息占位符,并将类名添加到输入中以供选择

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

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

答案 1 :(得分:0)

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

长短,您需要修改RequiredIf实施以考虑列表内容和其他可枚举属性,或者您需要添加一些手动验证来检查list实际上至少有一个项目。