在Asp.Net MVC中實現RequiredIf標簽對Model中的屬性進行驗證


在Asp.Net MVC中可以用繼承ValidationAttribute的方式,自定制實現RequiredIf標簽對Model中的屬性進行驗證

具體場景為:某一屬性是否允許為null的驗證,要根據另一個屬性值是否為true來判斷

 代碼如下所示:

1):后台代碼

    public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
    {
        private RequiredAttribute innerAttribute = new RequiredAttribute();
        public string DependentProperty { get; set; }
        public object TargetValue { get; set; }

        public RequiredIfAttribute(string dependentProperty, object targetValue)
        {
            this.DependentProperty = dependentProperty;
            this.TargetValue = targetValue;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var field = validationContext.ObjectInstance.GetType().GetProperty(DependentProperty);
            if (field != null)
            {
                var dependentValue = field.GetValue(validationContext.ObjectInstance, null);
                if (Object.Equals(dependentValue, TargetValue))
                {
                    if (!innerAttribute.IsValid(value))
                        return new ValidationResult(ErrorMessage);
                }
            }
            return ValidationResult.Success;
        }

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

            string depProp = BuildDependentPropertyId(metadata, context as ViewContext);

            // find the value on the control we depend on;
            // if it's a bool, format it javascript style 
            // (the default is True or False!)
            string targetValue = (TargetValue ?? "").ToString();
            if (TargetValue is bool)
                targetValue = targetValue.ToLower();

            rule.ValidationParameters.Add("dependentproperty", depProp);
            rule.ValidationParameters.Add("targetvalue", targetValue);

            yield return rule;
        }

        private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
        {
            // build the ID of the property
            string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(DependentProperty);
            // unfortunately this will have the name of the current field appended to the beginning,
            // because the TemplateInfo's context has had this fieldname appended to it. Instead, we
            // want to get the context as though it was one level higher (i.e. outside the current property,
            // which is the containing object, and hence the same level as the dependent property.
            var thisField = metadata.PropertyName + "_";
            if (depProp.StartsWith(thisField))
                // strip it off again
                depProp = depProp.Substring(thisField.Length);
            return depProp;
        }

    }

 

 2):前台代碼

$.validator.addMethod('requiredif', function (value, element, parameters) {
    var id = '#' + parameters['dependentproperty'];

    // get the target value (as a string, 
    // as that's what actual value will be)
    var targetvalue = parameters['targetvalue'];
    targetvalue = (targetvalue == null ? '' : targetvalue).toString();

    // get the actual value of the target control
    // note - this probably needs to cater for more 
    // control types, e.g. radios
    var control = $(id);
    if (control == null || control.length == 0) { // if control is null, the control is a checkbox or a radio
        control = $("[name='" + parameters['dependentproperty'] + "']:checked");
    }
    var controltype = control.attr('type');
    var actualvalue =
        (controltype === 'checkbox' || controltype === 'radio') ?
        control.val() != "" ? control.val() : control.prop('checked').toString() :
        control.val();

    // if the condition is true, reuse the existing 
    // required field validator functionality
    if ($.trim(targetvalue) === $.trim(actualvalue) || ($.trim(targetvalue) === '*' && $.trim(actualvalue) !== ''))
        return $.validator.methods.required.call(
            this, value, element, parameters);

    return true;
});

$.validator.unobtrusive.adapters.add('requiredif', ['dependentproperty', 'targetvalue'], function (options) {
    options.rules['requiredif'] = {
        dependentproperty: options.params['dependentproperty'],
        targetvalue: options.params['targetvalue']
    };
    options.messages['requiredif'] = options.message;
});

 

 將標簽RequiredIf添加到對應的屬性上

【注:第一個參數為相關聯的屬性名,第二個參數表示相關聯屬性值(相關聯屬性值=第二個參數時,再對此屬性進行驗證),第三個參數為錯誤提示信息】

        public class EricSunModel
        {
            public bool ContainsDangerousGoods { get; set; }

            [RequiredIf("ContainsDangerousGoods", true, ErrorMessage = "Please enter UN Number")]
            [Display(Name = "UN Number")]
            public string UNNumber { get; set; }
        }

 

更多細節請參考如下鏈接:

http://mvcdiary.com/2013/02/28/conditional-required-validation-or-field-mandatory-depends-on-another-field-mvc-4/ 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM