【问题标题】:Conditional RegularExpression validators in asp.netasp.net 中的条件正则表达式验证器
【发布时间】:2013-05-06 03:49:20
【问题描述】:

得到一个模型,其属性具有数据注释验证器属性。一个典型的例子是:

 [RegularExpression("^[a-z]{5,}$", ErrorMessage="required field, must have correct format")]
 public string SomeProperty {get;set; }

我需要使这些验证器有条件:如果模型中的特定属性具有特定值,则应禁用大多数验证器。 - 在服务器端和客户端。 ( (我使用的是标准 Ms Ajax 客户端验证)

没有使数据注释验证器有条件的默认方法,因此我四处寻找一些实现新型数据注释验证器的库。 查看了 Foolproof.codeplex.com 和 RequiredIf 验证属性。 但是我发现我要么无法正确实现它们,要么它们的实现过于简单(foolProof 只能让您检查单个条件)

对我来说最好的解决方案是,如果我可以为验证器提供 2 个参数:一个条件表达式和一个验证器。可能看起来像这样:

 [RequiredIf("OtherProperty == true", RegularExpression=@"^[a-z]{5,}$", ErrorMessage="required field, must have correct format")]
 public string SomeProperty {get;set; }

您还有其他推荐的库,或者我可以尝试的其他类型的解决方案吗?

【问题讨论】:

    标签: asp.net validation


    【解决方案1】:

    看起来你想使用万无一失的RegularExpressionIf验证器。

    【讨论】:

      【解决方案2】:

      您可以通过在模型中实现 IValidatableObject 来使用自定义验证,并执行您需要执行的任何条件。

      您需要实现Validate 方法。

      public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
      {
      
          if (condition)
              yield return new ValidationResult("Your error message", new string[] { "Info" });
      }
      

      【讨论】:

      • 这将迫使我为客户端验证添加单独的规则。宁愿不要。我喜欢能够在一个地方编写验证规则,之后它们在服务器端和客户端之间“同步”。
      【解决方案3】:

      是的,没有办法使用属性有条件地进行内置验证。仅仅是因为属性不是可选的。

      我建议你试试:https://fluentvalidation.codeplex.com/

      在任何情况下,您都需要通过上下文(如 Scartag 提及)或使用此流利的 API 手动处理 ValidationResult。

      【讨论】:

        【解决方案4】:

        我最近处理了一个类似的问题,我尝试了网上找到的各种解决方案,但收效甚微。

        最终我为此创建了一个新的自定义属性,这是我的实现,效果很好!

        • 创建一个新类:

          public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
          {
          
              private string DependentProperty { get; set; }
              private object DesiredValue { get; set; }
              private readonly RequiredAttribute _innerAttribute;
          
              public RequiredIfAttribute(string dependentProperty, object desiredValue)
              {
                  DependentProperty = dependentProperty;
                  DesiredValue = desiredValue;
                  _innerAttribute = new RequiredAttribute();
              }
          
              protected override ValidationResult IsValid(object value, ValidationContext validationContext)
              {
                  var dependentValue = validationContext.ObjectInstance.GetType().GetProperty(DependentProperty).GetValue(validationContext.ObjectInstance, null);
          
                  if (Regex.IsMatch(dependentValue.ToString(), DesiredValue.ToString()))
                  {
                      if (!_innerAttribute.IsValid(value))
                      {
                          return new ValidationResult(FormatErrorMessage(validationContext.DisplayName), new[] { validationContext.MemberName });
                      }
                  }
                  return ValidationResult.Success;
              }
          
              public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext controllerContext)
              {
                  var rule = new ModelClientValidationRule
                  {
                      ErrorMessage = ErrorMessageString,
                      ValidationType = "requiredif",
                  };
                  rule.ValidationParameters["dependentproperty"] = GetPropertyId(metadata, controllerContext as ViewContext);
                  rule.ValidationParameters["desiredvalue"] = DesiredValue is bool ? DesiredValue.ToString().ToLower() : DesiredValue;
          
                  yield return rule;
              }
          
              private string GetPropertyId(ModelMetadata metadata, ViewContext viewContext)
              {
                  string propertyId = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(DependentProperty);
                  var parentField = metadata.PropertyName + "_";
                  return propertyId.Replace(parentField, "");
              }
          }
          
        • 然后新建一个javascript文件:

          $.validator.unobtrusive.adapters.add('requiredif', ['dependentproperty', 'desiredvalue'], function (options) {
              options.rules['requiredif'] = options.params;
              options.messages['requiredif'] = options.message;
          });
          
          $.validator.addMethod('requiredif', function (value, element, parameters) {
              var desiredvalue = parameters.desiredvalue;
              desiredvalue = (desiredvalue == null ? '' : desiredvalue).toString();
              var controlType = $("input[id$='" + parameters.dependentproperty + "']").attr("type");
              var actualvalue = {}
              if (controlType == "checkbox" || controlType == "radio") {
                  var control = $("input[id$='" + parameters.dependentproperty + "']:checked");
                  actualvalue = control.val();
              } else {
                  actualvalue = $("#" + parameters.dependentproperty).val();
              }
              if ($.trim(actualvalue).match($.trim(desiredvalue))) {
                  var isValid = $.validator.methods.required.call(this, value, element, parameters);
                  return isValid;
              }
              return true;
          });
          

        显然,将您的这个 javascript 文件(在我的情况下为“custom-validation.js”)导入您的视图。

            <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
            <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
            <script src="@Url.Content("~/Scripts/custom-validation.js")"></script>
        
        • 然后,设置好之后,您就可以像使用其中一个标准属性一样使用它了:

          [RequiredIf("Country", @"^((?!USA).)*$", ErrorMessage = "Please specify a province if you're not from the United States.")]
          public string Province { get; set; }
          

        希望这可以帮助其他人解决这个问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多