【问题标题】:Custom Validation based on drop down selected value in MVC基于 MVC 中下拉选定值的自定义验证
【发布时间】:2016-12-18 16:34:13
【问题描述】:

我想根据另一个属性的值使用数据注释来验证一个属性。

我有一个人模型--

     public class People
        {
            [DisplayName("Your Name")]
            [Required]
            public string Name { get; set; }
            [Required]
            public string Gender { get; set; }    
            [DisplayName("Your Age")]
            [Required]
            // Another Attribute here for my custom validation
            public int Age { get; set; }              

         }

和索引:

public ActionResult Index()
        {
            IList<SelectListItem> types = new List<SelectListItem>();           
            types.Add(new SelectListItem() { Text = "Male", Value = "M" });
            types.Add(new SelectListItem() { Text = "Female", Value = "F" });
            ViewBag.ItemTypes = types;

            return View();
        }

'Gender' 绑定到一个下拉列表,并基于所选的 Gender 我要验证 'Age' 属性。

  • 如果选择男性,则年龄范围必须介于 22 到 60 岁之间。
  • 如果选择了女性,则年龄范围必须介于 18 到 58 岁之间。

必须有一个自定义验证属性,但我无法弄清楚。

我的观点:

@using (Html.BeginForm("Index", "Test", FormMethod.Post))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>TimeRecord</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Gender, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.Gender, (IEnumerable<SelectListItem>)ViewBag.ItemTypes, new { @class = "form-control" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Name, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(m => m.Age, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.Age, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.Age, "", new { @class = "text-danger" })
            </div>
        </div>


        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>

    </div>
}

【问题讨论】:

标签: asp.net-mvc


【解决方案1】:

您可以创建自定义验证属性,因为它适用于验证单个属性(单个属性级验证),请查看以下代码 sn-p。

namespace SO.Models
{
    using Helpers;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;

    public class Person
    {
        // code omitted for brevity

        [DisplayName("Your Age")]
        [Required]
        [PersonAge(minMaleAge: 22, maxMaleAge: 60, minFemaleAge: 18, maxFemaleAge: 58)]
        public int Age { get; set; }
    }
}

namespace SO.Helpers
{
    using Models;
    using System.ComponentModel.DataAnnotations;

    public class PersonAgeAttribute : ValidationAttribute
    {
        private const string _validationMessage = "Age should be between {0} and {1}";

        private int _minMaleAge;

        private int _maxMaleAge;

        private int _minFemaleAge;

        private int _maxFemaleAge;

        public PersonAgeAttribute(int minMaleAge, int maxMaleAge, int minFemaleAge, int maxFemaleAge)
        {
            _minMaleAge = minMaleAge;
            _maxMaleAge = maxMaleAge;
            _minFemaleAge = minFemaleAge;
            _maxFemaleAge = maxFemaleAge;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            Person person = (Person)validationContext.ObjectInstance;

            if (person.Gender == "M" && (person.Age < _minMaleAge || person.Age > _maxMaleAge))
            {
                return new ValidationResult(GetErrorMessage(person.Gender));
            }
            else if (person.Gender == "F" && (person.Age < _minFemaleAge || person.Age > _maxFemaleAge))
            {
                return new ValidationResult(GetErrorMessage(person.Gender));
            }

            return ValidationResult.Success;
        }

        private string GetErrorMessage(string gender)
        {
            if (gender == "M")
            {
                return string.Format(_validationMessage, _minMaleAge, _maxMaleAge);
            }
            else
            {
                return string.Format(_validationMessage, _minFemaleAge, _maxFemaleAge);
            }
        }
    }
}

另外,IValidatableObject 接口可以通过实现其Validate 方法来实现类级验证。更多信息请查看Class-Level Model Validation

【讨论】:

    【解决方案2】:

    根据我的理解,根据您的要求,解决方案可能是这样的。

    对于服务器端验证,请创建您自己的自定义端验证属性。要启用客户端验证,请继承“IClientValidatable”。

     [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
    public class AgeForGenderAttribute : ValidationAttribute, IClientValidatable
    {
        private string _PropertyToCompare { get; set; }
        private string CurrentPropertyValue { get; set; }
        public int _MinAgeForMale { get; set; }
        public int _MaxAgeForMale { get; set; }
        public int _MinAgeForFemale { get; set; }
        public int _MaxAgeForFemale { get; set; }
        string relevantErrorMessage { get; set; }
    
        public AgeForGenderAttribute(string PropertyToCompare, int MinAgeForMale, int MaxAgeForMale, int MinAgeForFemale, int MaxAgeForFemale, string validationMessage)
        {
            this._PropertyToCompare = PropertyToCompare;
            this._MinAgeForMale = MinAgeForMale;
            this._MaxAgeForMale = MaxAgeForMale;
            this._MinAgeForFemale = MinAgeForFemale;
            this._MaxAgeForFemale = MaxAgeForFemale;
            ErrorMessage = validationMessage;
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var comparePropertyInfo = validationContext.ObjectType.GetProperty(_PropertyToCompare);
            object dependentPropertyValue = comparePropertyInfo.GetValue(validationContext.ObjectInstance, null);
            CurrentPropertyValue = dependentPropertyValue.ToString();
            var currentValue = (int)value;
            if (dependentPropertyValue != null)
            {
                switch (CurrentPropertyValue)
                {
                    case "M":
                        if (currentValue < _MinAgeForMale || currentValue > _MaxAgeForMale)
                        {
                            ErrorMessage = string.Format(ErrorMessage, _MinAgeForMale, _MaxAgeForMale);
                            return new ValidationResult(ErrorMessage);
                        }
                        break;
                    case "F":
                        if (currentValue < _MinAgeForFemale || currentValue > _MaxAgeForFemale)
                        {
                            ErrorMessage = string.Format(ErrorMessage, _MinAgeForMale, _MaxAgeForMale);
                            return new ValidationResult(ErrorMessage);
                        }
                        break;
                }
            }
    
            return ValidationResult.Success;
        }
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rules = new ModelClientValidationRule
            {
                ValidationType = "conditionalrange",
                ErrorMessage = ErrorMessage
            };
    
            rules.ValidationParameters.Add("condiotionalpropertyname", _PropertyToCompare);
            rules.ValidationParameters.Add("minageformale", _MinAgeForMale);
            rules.ValidationParameters.Add("maxageformale", _MaxAgeForMale);
            rules.ValidationParameters.Add("minageforfemale", _MinAgeForFemale);
            rules.ValidationParameters.Add("maxageforfemale", _MaxAgeForFemale);
            yield return rules;
        }
    
    }
    

    你的js:

        $(function () {
    
        $.validator.addMethod("conditionalrange", function (value, element, params) {
             var condiotionalpropertyname = $('#' + params.condiotionalpropertyname).val();
            var retVal = true;
            switch (condiotionalpropertyname) {
                case 'M':
                    if (value < params.minageformale || value > params.maxageformale) {
                        retVal = false;
                    }
                    break;
                case "F":
                    if (value < params.minageforfemale || value > params.maxageforfemale) {
                        retVal = false;
                    }
                    break;
            }      
    
            return retVal;
        });
    
        $.validator.unobtrusive.adapters.add("conditionalrange", ['condiotionalpropertyname', 'minageformale', 'maxageformale', 'minageforfemale', 'maxageforfemale'],
        function (options) {
            options.rules['conditionalrange'] = {
                condiotionalpropertyname: options.params.condiotionalpropertyname,
                minageformale: options.params.minageformale,
                maxageformale: options.params.maxageformale,
                minageforfemale: options.params.minageforfemale,
                maxageforfemale: options.params.maxageforfemale
            };
            options.messages['conditionalrange'] = options.message;
        }
        );
    }(jQuery));
    

    它将完全按照您的要求工作。确保您已包含所有相关的 js。

    属性:

            [DisplayName("Your Age")]
            [Required]
            [AgeForGender("Gender", 18, 45, 22, 60, "Age should be between {0} and {1}")]
            public int Age { get; set; }
    

    【讨论】:

    • 谢谢!!让我检查一下。
    • 如何根据您的回答装饰房产。
    猜你喜欢
    • 2017-12-04
    • 2021-11-15
    • 1970-01-01
    • 2020-08-05
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-19
    相关资源
    最近更新 更多