ASP.NET MVC custom multiple fields validation

前端 未结 1 1141
我寻月下人不归
我寻月下人不归 2021-01-13 12:20

I\'m developing an ASP.NET MVC 5.2.3 custom data annotation for validation in Visual Studio 2015. It needs to take any number of fields and ensure that if one has a value, t

相关标签:
1条回答
  • 2021-01-13 13:10

    In order to get client side validation, you need to pass the values of the 'other properties' in the ModelClientValidationRule by using the .Add() method of the rules ValidationParameters property, and then write the client side scripts to add the rules to the $.validator.

    But first there are a few other issues to address with your attribute. First you should execute your foreach loop only if the value of the property you applied the attribute is null. Second, returning a ValidationResult if one of the 'other properties' does not exist is confusing and meaningless to a user and you should just ignore it.

    The attribute code should be (note I changed the name of the attribute)

    public class RequiredIfAnyAttribute : ValidationAttribute, IClientValidatable
    {
        private readonly string[] _otherProperties;
        private const string _DefaultErrorMessage = "The {0} field is required";
    
        public RequiredIfAnyAttribute(params string[] otherProperties)
        {
            if (otherProperties.Length == 0) // would not make sense
            {
                throw new ArgumentException("At least one other property name must be provided");
            }
            _otherProperties = otherProperties;
            ErrorMessage = _DefaultErrorMessage;
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null) // no point checking if it has a value
            {
                foreach (string property in _otherProperties)
                {
                    var propertyName = validationContext.ObjectType.GetProperty(property);
                    if (propertyName == null)
                    {
                        continue;
                    }
                    var propertyValue = propertyName.GetValue(validationContext.ObjectInstance, null);
                    if (propertyValue != null)
                    {
                        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
                    }
                }
            }
            return ValidationResult.Success;
        }
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ValidationType = "requiredifany",
                ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            };
            / pass a comma separated list of the other propeties
            rule.ValidationParameters.Add("otherproperties", string.Join(",", _otherProperties));
            yield return rule;
        }
    }
    

    The scripts will then be

    sandtrapValidation = {
        getDependentElement: function (validationElement, dependentProperty) {
            var dependentElement = $('#' + dependentProperty);
            if (dependentElement.length === 1) {
                return dependentElement;
            }
            var name = validationElement.name;
            var index = name.lastIndexOf(".") + 1;
            var id = (name.substr(0, index) + dependentProperty).replace(/[\.\[\]]/g, "_");
            dependentElement = $('#' + id);
            if (dependentElement.length === 1) {
                return dependentElement;
            }
            // Try using the name attribute
            name = (name.substr(0, index) + dependentProperty);
            dependentElement = $('[name="' + name + '"]');
            if (dependentElement.length > 0) {
                return dependentElement.first();
            }
            return null;
        }
    }
    
    $.validator.unobtrusive.adapters.add("requiredifany", ["otherproperties"], function (options) {
        var element = options.element;
        var otherNames = options.params.otherproperties.split(',');
        var otherProperties = [];
        $.each(otherNames, function (index, item) {
            otherProperties.push(sandtrapValidation.getDependentElement(element, item))
        });
        options.rules['requiredifany'] = {
            otherproperties: otherProperties
        };
        options.messages['requiredifany'] = options.message;
    });
    
    $.validator.addMethod("requiredifany", function (value, element, params) {
        if ($(element).val() != '') {
            // The element has a value so its OK
            return true;
        }
        var isValid = true;
        $.each(params.otherproperties, function (index, item) {
            if ($(this).val() != '') {
                isValid = false;
            }
        });
        return isValid;
    });
    
    0 讨论(0)
提交回复
热议问题