自定义验证基于MVC中的下拉选择值

时间:2016-12-17 17:12:06

标签: asp.net-mvc

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

我有一个人模型 -

     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();
        }

&#39;性别&#39;被绑定到下拉列表,并根据我想要验证的所选性别&#39;年龄&#39;属性。

  • 如果选择了男性,则年龄范围必须在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>
}

2 个答案:

答案 0 :(得分:2)

您可以创建自定义验证属性,因为它可以很好地验证各个属性(单个属性级别验证),请查看以下代码段。

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

答案 1 :(得分:0)

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

对于服务器端验证,请创建自己的自定义验证属性。要启用客户端验证,请继承“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));

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

属性:

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