【问题标题】:ASP.NET MVC custom validator client-side validation not firingASP.NET MVC 自定义验证器客户端验证未触发
【发布时间】:2015-12-10 22:38:28
【问题描述】:

我创建了一个自定义组验证器,以确保用户至少填写了给定组中的一个字段。这在我加载页面并提交表单而不输入任何内容时有效。

无效的表格

有效形式

但是,问题在于表单出现除组验证错误之外的任何错误。当我强制表单显示组所需的验证错误,然后在组中的一个字段上显示字符串长度错误时,组验证错误不会消失。

经过一些调试,我相当确定它的客户端验证无法正常工作,因为它不会在生成客户端验证时消除服务器端验证错误。当表单生成字符串长度错误时,它会阻止将表单发布到服务器,这将删除需要组验证的错误。

任何人都可以看到客户端验证代码的问题吗?我从这个 stackoverflow 页面MVC3 unobtrusive validation group of inputs 复制了代码,并对其进行了更改以满足我的需要。这是我第一次尝试自定义验证,如果问题非常简单,请原谅我。另一个指标是,每当我输入然后删除单个字符时,组验证错误不会打开/关闭。

我在下面提供了自定义验证器代码:

自定义验证器 C#(服务器端和客户端)

public class RequireAtLeastOneIfAttribute : ValidationAttribute, IClientValidatable
{
    private string[] Properties { get; set; }
    public RequireAtLeastOneIfAttribute(params string[] properties)
    {
        Properties = properties;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      if(Properties == null || Properties.Length < 1)
      {
         return null;
      }

      foreach (var property in Properties)
      {
         var propertyInfo = validationContext.ObjectType.GetProperty(property);
         var propertyValue = propertyInfo.GetValue(validationContext.ObjectInstance, null);

         if (propertyInfo == null)
         {
            return new ValidationResult(string.Format("Unknown property {0}", property));
         }

         if (propertyValue is string & !string.IsNullOrEmpty(propertyValue as string))
         {
            return null;
         } 

         if (propertyValue != null)
         {
            return null;
         }
      }

      return new ValidationResult("At least one age group field is required");
   }

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

      rule.ValidationParameters["properties"] = string.Join(",", Properties);

      yield return rule;
   }
}

Javascript

我对 javascript 所做的唯一更改是 id。

jQuery.validator.unobtrusive.adapters.add(
    'requireatleaseoneif', ['properties'], function (options) {
        options.rules['requireatleaseoneif'] = options.params;
        options.messages['requireatleaseoneif'] = options.message;
    }
);

jQuery.validator.addMethod('requireatleaseoneif', function (value, element, params) {
    var properties = params.properties.split(',');
    var values = $.map(properties, function (property, index) {
        var val = $('#' + property).val();
        return val != '' ? val : null;
    });
    return values.length > 0;
}, '');

剃须刀

@Html.RadioButtonFor(m => m.HaveDependants, true, new { id = "borrower-haveDependants-true", @class = "block-radio-input" })
@Html.RadioButtonFor(m => m.HaveDependants, false, new { id = "borrower-haveDependants-false", @class = "block-radio-input" })             
@Html.ValidationMessageFor(m => m.HaveDependants)

@Html.LabelFor(m => m.DependantsAgeGroupOne)                            
@Html.TextBoxFor(m => m.DependantsAgeGroupOne, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.DependantsAgeGroupOne)

@Html.LabelFor(m => m.DependantsAgeGroupTwo)
@Html.TextBoxFor(m => m.DependantsAgeGroupTwo, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.DependantsAgeGroupTwo)

@Html.LabelFor(m => m.DependantsAgeGroupThree)
@Html.TextBoxFor(m => m.DependantsAgeGroupThree, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.DependantsAgeGroupThree)

我还认为问题可能在于其触发方式。因为验证属性不在文本输入本身上,而是在单选按钮上,所以我添加了以下 javascript 以在按钮单击时验证整个表单。

<script>
    $(document).ready(function () {
        $(form).validate;
    });
</script>

我把 Javascript 的最后一位改成如下

$('input').blur(function () {
   $('.haveDependants').valid();
})

【问题讨论】:

  • 一半的服务器端代码丢失。此外,通过更改 javascript 代码中的“id”,您的意思是您决定应该将有意义的名称 atleastonerequired 更改为不正确的名称 requireatleaseoneif?干得好!
  • 你需要把你的两分钱放进去吗?你的回答没有帮助。如果你知道这个洞的故事,那确实是有道理的。 'requireatleastoneif - 单选按钮设置为 true。因此,将来您可以将您的智能 cmets 留给自己。谢谢!
  • 您的代码存在一些潜在问题。无论HaveDependants 的值如何,验证都将被触发,并且我假设您只希望它在名称 RequireAtLeastOneIf 所指示的值为 true 时触发(您实际上在哪里检查该值)。如果这是一个复杂对象的一部分,因为您使用了var val = $('#' + property).val();,下一次验证将失败。但是您显示的最后一个脚本只是在首次加载文档时验证表单,而不是单击按钮您发布了正确的代码吗?
  • 是的,我的意图是仅验证单选按钮是否为真,但我试图让客户端组验证按原样工作。从那以后我想到最后一段 JavaScript 是错误的。我已将新代码添加到问题中,但这也不起作用。
  • @CodeMonkey(看看这条评论是如何开始的)。您的单选按钮没有class='haveDependants',所以$('.haveDependants').valid(); 什么都不做,因为没有具有该类名的元素

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


【解决方案1】:

我的自定义验证属性也有同样的问题。默认属性阻止将表单发布到服务器,并且我的自定义属性被忽略。所以这就是我所做的。

  1. 禁用客户端表单验证:

    @{ Html.EnableClientValidation(false); }

  2. 在被调用的控制器中:

if (!ModelState.IsValid) { return View(model); }

【讨论】:

    猜你喜欢
    • 2010-10-16
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 2013-11-23
    • 2017-05-08
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多