Аннотации данных, ненавязчивая проверка. Минимальный возраст, максимальный возраст

Чего я хочу добиться:

  1. Чтобы отобразить отдельное сообщение проверки для неудачной проверки минимального возраста и одно для проверки максимального возраста
  2. Для хранения минимального и максимального возраста в одной области в виде целых чисел. Не в js/валидаторе... только в модели. который я надеюсь изменить, чтобы посмотреть файл конфигурации.
  3. Чтобы валидация работала с jquery ненавязчиво и на стороне сервера, и чтобы была в одном месте против модели (и обв какой-то jquery)
  4. Для включения с помощью аннотаций данных
  5. Я хотел проверить DOB как дату и время, чтобы пользователь не указал возраст как int. Если бы я это сделал, я мог бы использовать обозначение [Min] и [Max] для возраста. Это было недостаточно хорошо.
  6. Почему я не использовал обозначение диапазона. Я хотел запустить другое сообщение проверки для каждого минимального сбоя и максимального сбоя. Я смотрел на это и не смотрел. Мне также пришлось бы передать диапазон как datetime и его статику или что-то в этом роде, поэтому я не мог бы, например, сделать DateTime.Now.AddYears(-90).

Мои проблемы

  1. Я новичок в MVC, проверке JQuery и всей архитектуре MVC!
  2. То, что я придумал, работает. Однако, как вы можете видеть, код повторяется, и я хотел бы соответствовать DRY.
  3. Мой первый хак заключался в том, чтобы передать значение, которое я проверяю, в сообщение проверки. Я обошел это, сделав...

    [MaximumAgeCheck(90,"Для подачи заявки вам должно быть не более {0}")]

и внутри атрибута проверки

    private readonly int _min;
    private readonly string _defaultErrorMessage = "";
    public MinimumAgeCheck(int min, string defaultErrorMessage)
        : base(defaultErrorMessage)
    {
        _min = min;
        _defaultErrorMessage = defaultErrorMessage.Replace("{0}", _min.ToString());
    }

и я использовал его, например, так ..

return new ValidationResult(_defaultErrorMessage);

Я знаю, что это неправильный способ сделать это, и мне интересно, как это сделать лучше всего?

Второй взлом!

Я передаю два параметра проверки, к которым я хочу иметь доступ в методе jQuery.validator.addMethod....

Я попытался получить доступ к этим параметрам, выполнив следующие действия... params.[thevalueiadded], params[0]... и т. д., я даже вывел параметры в console.log, но он никогда не показывал мне все параметры, только первое значение как струна!

Моя работа заключалась в том, чтобы хранить переменные javascript вверху и загружать их из adapters.add.

Я, вероятно, мало что понимаю, поэтому вот код, который работает... Предупреждаю, он беспорядочный!

Свойство модели и аннотация данных

[Required(ErrorMessage = "Date of birth required")]
        [Display(Name = "Date of Birth")]
        [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
        [DataType(DataType.DateTime, ErrorMessage = "Date of birth should be in dd/mm/yyyy format")]
        [MinimumAgeCheck(18,"You have to be at least {0} to apply")]
        [MaximumAgeCheck(90,"You have to be at most {0} to apply")]
        public DateTime? DateOfBirth { get; set; }

Проверка минимального и максимального возраста

атрибуты проверки

public class MinimumAgeCheck : ValidationAttribute, IClientValidatable
    {
        private readonly int _min;
        private readonly string _defaultErrorMessage = "";
        public MinimumAgeCheck(int min, string defaultErrorMessage)
            : base(defaultErrorMessage)
        {
            _min = min;
            _defaultErrorMessage = defaultErrorMessage.Replace("{0}", _min.ToString());
        }


        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            DateTime dtV = (DateTime)value;
            long lTicks = DateTime.Now.Ticks - dtV.Ticks;
            DateTime dtAge = new DateTime(lTicks);

            if (!(dtAge.Year >= _min && dtAge.Year <= 30))
            {
                return new ValidationResult(_defaultErrorMessage);
            }
            return ValidationResult.Success;
        }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString, _min);
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            ModelClientValidationRule mcvrTwo = new ModelClientValidationRule();
            mcvrTwo.ValidationType = "checkminimumage";
            mcvrTwo.ErrorMessage = _defaultErrorMessage;
            mcvrTwo.ValidationParameters.Add("todaysdate", DateTime.Now.ToString("dd/MM/yyyy"));
            mcvrTwo.ValidationParameters.Add("lowerage", _min.ToString());

            return new List<ModelClientValidationRule> { mcvrTwo };
        }
    }


  public class MaximumAgeCheck : ValidationAttribute, IClientValidatable
    {
        private readonly int Max;
        private readonly string _defaultErrorMessage = "";
        public MaximumAgeCheck(int max, string defaultErrorMessage)
            : base(defaultErrorMessage)
        {
            Max = max;
            _defaultErrorMessage = defaultErrorMessage.Replace("{0}", Max.ToString());
        }


        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            DateTime dtV = (DateTime)value;
            long lTicks = DateTime.Now.Ticks - dtV.Ticks;
            DateTime dtAge = new DateTime(lTicks);

            if (!(dtAge.Year >= Max && dtAge.Year <= 30))
            {
                return new ValidationResult(_defaultErrorMessage);
            }
            return ValidationResult.Success;
        }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,Max);
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            ModelClientValidationRule mcvrTwo = new ModelClientValidationRule();
            mcvrTwo.ValidationType = "checkmaximumage";
            mcvrTwo.ErrorMessage = _defaultErrorMessage;
            mcvrTwo.ValidationParameters.Add("todaysdate", DateTime.Now.ToString("dd/MM/yyyy"));
            mcvrTwo.ValidationParameters.Add("upperage", Max.ToString());

            return new List<ModelClientValidationRule> { mcvrTwo };
        }
    }

JQuery

(function ($) {

    var mintodaysDateVal;
    var maxtodaysDateVal;
    var lowerageVal;
    var upperageVal;
    jQuery.validator.unobtrusive.adapters.add("checkminimumage", ['lowerage', 'todaysdate', 'upperage'], function (options) {
        options.rules["checkminimumage"] = options.params;

        mintodaysDateVal = options.params.todaysdate;
        lowerageVal = options.params.lowerage;

        options.messages["checkminimumage"] = options.message;
    });



    jQuery.validator.addMethod("checkminimumage", function (value, element, params) {

        var currDate = mintodaysDateVal;
        var sdoc = currDate.split('/');
        var dobDate = value;
        var sdob = dobDate.split('/');



        //pass year,month,date in new Date object.
        var vDOB = new Date(sdob[2], sdob[1] - 1, sdob[0]);
        var vDOC = new Date(sdoc[2], sdoc[1] - 1, sdoc[0]);
        //getAge user define function to calculate age.

        var vYrs = getAge(vDOB, vDOC);
        var result = false;
        if (vYrs >= lowerageVal) { result = true; }
        return result;
    });



    jQuery.validator.unobtrusive.adapters.add("checkmaximumage", ['lowerage', 'todaysdate', 'upperage'], function (options) {
        options.rules["checkmaximumage"] = options.params;

        maxtodaysDateVal = options.params.todaysdate;
        upperageVal = options.params.upperage;

        options.messages["checkmaximumage"] = options.message;
    });



    jQuery.validator.addMethod("checkmaximumage", function (value, element, params) {
        var currDate = maxtodaysDateVal;
        var sdoc = currDate.split('/');
        var dobDate = value;
        var sdob = dobDate.split('/');

        var vDOB = new Date(sdob[2], sdob[1] - 1, sdob[0]);
        var vDOC = new Date(sdoc[2], sdoc[1] - 1, sdoc[0]);

        var vYrs = getAge(vDOB, vDOC);
        var result = false;
        if (vYrs <= upperageVal) { result = true; }
        return result;
    });


    function getAge(oldDate, currDate) {
        return currDate.getFullYear() - oldDate.getFullYear();
    }
} (jQuery));

Я надеюсь, что это имеет смысл, я прочитал его, и он довольно искажен... так что я буду рад ответить на любые комментарии.




Ответы (2)


Действительно полезный код, но метод ValidationResult IsValid содержит несколько ошибок. Он не обрабатывает будущие даты или пустые даты. Кроме того, кажется, что у него есть жестко запрограммированное ограничение до 30 лет - похоже, это отладочный код? Во всяком случае, я решил эти проблемы для своего кода и придумал следующее:

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
        {
            return new ValidationResult(_defaultErrorMessage);
        }

        DateTime dtV = (DateTime)value;
        long lTicks = DateTime.Now.Ticks - dtV.Ticks;
        if (lTicks < 0)
        {
            return new ValidationResult(_defaultErrorMessage);
        }

        DateTime dtAge = new DateTime(lTicks);

        if (!(dtAge.Year >= _min ))
        {
            return new ValidationResult(_defaultErrorMessage);
        }
        return ValidationResult.Success;
    }
person StuartQ    schedule 04.10.2012

Взгляните на библиотеку валидации MVC Foolproof. Вы можете найти его в NuGet.

Он имеет практически всю необходимую проверку и добавляется с помощью аннотаций данных. Он прекрасно интегрируется в ненавязчивую проверку на стороне клиента.

person Si Robinson    schedule 04.10.2012