【问题标题】:How can I validate two-variable rules in client-side validation?如何在客户端验证中验证两个变量规则?
【发布时间】:2015-02-24 01:02:55
【问题描述】:

我有以下 poco:

public class CabinetItem
{
    [Required]
    [Display(...)]
    public double Width { get; set; }

    public double MinWidth { get; }
}

我想弄清楚的是,当MinWidth 可能是什么时,我如何验证Width 大于MinWidth?最小宽度是取决于橱柜项目的约束。注意:还有一个MaxWidth,为了简化这个问题,我省略了。

【问题讨论】:

  • 查看我的答案,它包括不显眼的验证

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


【解决方案1】:

选项 1:

foolproof nuget 包在您的情况下可能非常有用。

安装foolproof nuget 包并使用其额外有用的属性,如下所示:

public class CabinetItem
{
    [Required]
    [Display(...)]
    [GreaterThan("MinWidth")]
    public double Width { get; set; }

    public double MinWidth { get; }
}

还有其他功能:

  • [是]
  • [等于]
  • [NotEqualTo]
  • [大于]
  • [小于]
  • [GreaterThanOrEqualTo]
  • [LessThanOrEqualTo]

资源: Is there a way through data annotations to verify that one date property is greater than or equal to another date property?

【讨论】:

  • 您链接到的自定义验证属性仅适用于 Silverlight。我相信 MVC 的类比是 ValidationAttribute。如果不是这样,请纠正我。
  • 我已经看到了,但这不需要发回服务器来验证吗?这就是不显眼的验证在幕后所做的吗?
  • 是的,第一个是正确的,我将删除它,但第二个不显眼的 ajax 可以是任何 get/post 方法。请看asp.net/mvc/overview/older-versions/…
【解决方案2】:

您可以创建CustomValidationAttribute

以此为例:

    public class GreaterThanAttribute : ValidationAttribute, IClientValidatable
    {
        private readonly string _testedPropertyName;
        private readonly bool _allowEqualValues;
        private readonly string _testedPropertyDisplayName;

        public override string FormatErrorMessage(string displayName)
        {
            return string.Format(ErrorMessages.GreaterThan_Message, displayName, _testedPropertyDisplayName);
        }

        public GreaterThanAttribute(string testedPropertyName, Type resourceType, string testedPropertyDisplayNameKey, bool allowEqualValues = false)
        {
            _testedPropertyName = testedPropertyName;
            _allowEqualValues = allowEqualValues;
            var rm = new ResourceManager(resourceType);
            _testedPropertyDisplayName = rm.GetString(testedPropertyDisplayNameKey);            
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var propertyTestedInfo = validationContext.ObjectType.GetProperty(_testedPropertyName);

            if (propertyTestedInfo == null)
            {
                return new ValidationResult(string.Format("unknown property {0}", _testedPropertyName));
            }

            var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);

            if (value == null || !(value is Decimal))
            {
                return ValidationResult.Success;
            }

            if (propertyTestedValue == null || !(propertyTestedValue is Decimal))
            {
                return ValidationResult.Success;
            }

            // Compare values
            if ((Decimal)value >= (Decimal)propertyTestedValue)
            {
                if (_allowEqualValues && value == propertyTestedValue)
                {
                    return ValidationResult.Success;
                }
                else if ((Decimal)value > (Decimal)propertyTestedValue)
                {
                    return ValidationResult.Success;
                }
            }

            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = FormatErrorMessage(metadata.DisplayName),
                ValidationType = "greaterthan"
            };
            rule.ValidationParameters["propertytested"] = _testedPropertyName;
            rule.ValidationParameters["allowequalvalues"] = _allowEqualValues;
            yield return rule;
        }
    }

你可以这样使用它:

public Decimal MyProperty1 { get; set; }

[GreaterThanAttribute("MyProperty1", typeof(Strings), "Error_String")]
public Decimal MyProperty2 { get; set; }

[GreaterThanAttribute("MyProperty2", typeof(Strings), "Error_String")]
public Decimal MyProperty3 { get; set; }

在客户端,您可以添加它以进行客户端验证:

jQuery.validator.unobtrusive.adapters.add('greaterthan', ['propertytested', 'allowequalvalues'], function (options) {
            options.params["allowequalvalues"] = options.params["allowequalvalues"] === "True" ||
                                                 options.params["allowequalvalues"] === "true" ||
                                                 options.params["allowequalvalues"] === true ? true : false;

            options.rules['greaterthan'] = options.params;
            options.messages['greaterthan'] = options.message;
        });
jQuery.validator.addMethod("greaterthan", function (value, element, params) {        
            var properyTestedvalue= $('input[name="' + params.propertytested + '"]').val();
            if (!value || !properyTestedvalue) return true;
            return (params.allowequalvalues) ? parseFloat(properyTestedvalue) <= parseFloat(value) : parseFloat(properyTestedvalue) < parseFloat(value);
        }, ''); 

【讨论】:

  • 这可能有效。但我不会直接向客户端发出最大宽度。我是一个隐藏的价值。
  • 这不是一个真正的问题,因为$('input[name="' + params.propertytested + '"]') 甚至会获得一个隐藏字段
  • 你必须使用@Html.HiddenFor(m=&gt;m.MinWith)来渲染隐藏字段
猜你喜欢
  • 2021-02-27
  • 2019-02-13
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
  • 2019-01-29
  • 2011-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多