MVC2 Проверка на стороне клиента для DateTime? - PullRequest
8 голосов
/ 15 августа 2010

Какой подход вы рекомендуете для проверки DateTime на стороне клиента в MVC?

Допустим, у меня есть модель со свойством с именем DateOfBirth, равным DateTime, вот так.

public class UserModel
{
    [DataType(DataType.Date)]
    public DateTime DateOfBirth {get;set;}
}

На виде у меня есть простой

<%: Html.LabelFor(model=>model.DateOfBirth) %>
<%: Html.EditorFor(model=>model.DateOfBirth) %>
<%: Html.ValidationMessageFor(model=>model.DateOfBirth) %>
<input type="submit" value="Submit" />

Я могу использовать либо проверки Microsoft MVC, либо проверки jQuery. Как мне получить DateTime для проверки на стороне клиента?

Я понимаю, что все, что делает DataTypeAttribute - это предоставляет подсказки по форматированию и не выполняет никакой проверки (это оставляет эту часть для ModelBinder).

По сути, я хочу дублировать действия ModelBinder, когда он пытается поместить опубликованное значение в свойство DateOfBirth модели.

Каковы ваши рекомендации?

Ответы [ 4 ]

4 голосов
/ 03 сентября 2010

Как указано выше, следуйте посту Фила Хаака о пользовательских проверках: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

Вот как я бы это сделал:


  1. Добавьте класс "DateFormatAttribute"вот так:

    public class DateFormatAttribute : ValidationAttribute {
      public override bool IsValid(object value) {    
        if (value == null) {
          return true;
        }

        // Note: the actual server side validation still has to be implemented :-)
        // Just returning true now...

        return true;
      }
    }

Добавить класс DateFormatValidator, например, так:

    public class DateFormatValidator : DataAnnotationsModelValidator 
    {
      string message;

      public PriceValidator(ModelMetadata metadata, ControllerContext context
        , DateFormatAttribute attribute)
        : base(metadata, context, attribute) 
      {
        message = attribute.ErrorMessage;
      }

      public override IEnumerable GetClientValidationRules() 
      {
        var rule = new ModelClientValidationRule {
          ErrorMessage = message,
          ValidationType = "date" // note that this string will link to the JavaScript function we'll write later on
        };

        return new[] { rule };
      }
    }

Зарегистрируйте вышеупомянутые классы где-нибудь в Global.asax.cs:

    DataAnnotationsModelValidatorProvider
        .RegisterAdapter(typeof(DateFormatAttribute), typeof(DateFormatValidator));

Добавить функцию проверки на клиенте.Обратите внимание, что это должно быть реализовано в соответствии с языком пользователя.Ниже приведена голландская (nl-NL, nl-BE) функция проверки на стороне клиента:

    /*
     * Localized default methods for the jQuery validation plugin.
     * Locale: NL
     */
    jQuery.extend(jQuery.validator.methods, {
        date: function(value, element) {
            return this.optional(element) || /^\d\d?[\.\/-]\d\d?[\.\/-]\d\d\d?\d?$/.test(value);
        }
    });

Это должно охватывать вещи ...

1 голос
/ 06 сентября 2010

Джош,

Ваша проблема является довольно распространенной проблемой в MVC, которая заключается в том, что связыватель модели пытается связать введенные значения из формы в модель.очевидно, если он не «уместится», вы сразу же получите ошибку.

так как же мне заставить связыватель модели использовать мою пользовательскую проверку?и вернуть мое сообщение об ошибке?

ну, сначала прочитайте и сделайте то, что написал Фил Хаак.тогда у вас есть пользовательская проверка.

следующая вещь.Не используйте целые числа и даты в вашей модели!Если пользователь может ввести все, что он хочет, в текстовое поле, это всегда вызовет проблемы.

Что вы должны сделать, это создать flatObject вашего объекта.

Плоский объект довольно прост.Это объект, точная копия переменных внутри, только inst и datetime являются строками (потому что те всегда связываются в связывателе моделей)

пример:

namespace MVC2_NASTEST.Models {

    public partial class FlatNieuw {
        public int Niw_ID { get; set; }
        public string Niw_Datum { get; set; }
        public string Niw_Titel { get; set; }
        public string Niw_Bericht { get; set; }
        public int Niw_Schooljaar { get; set; }
        public bool Niw_Publiceren { get; set; }
    }
}

единственные целые числа iесть из выпадающих списков, потому что они не терпят неудачу, если значение в выпадающих списках является целым числом.дата (дата) является строкой.я делаю пользовательскую проверку для этой строки.связыватель моделей связывается с этим объектом FlatNieuw.

мой класс Nieuw имеет точно такие же имена полей, что и этот класс.поэтому, когда вы используете UpdateModel (), это все еще работает.Если вы делаете новую запись, вы можете использовать automapper для сопоставления этого flatObject с вашим обычным объектом.

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

0 голосов
/ 09 сентября 2010

Согласно моему опыту, иногда проверки Microsoft MVC или проверки jQuery являются избыточным убийством для некоторых проектов, которые мы разрабатываем.вот почему иногда я сам кодирую / беру маленькие из них.

Решение первое: Пользовательский плагин (вы можете изменить его так, как вам удобно)

(function($) {
    $.fn.extend({
            ValidateInput: function() {
                var bValid = true;
                this.removeClass('ui-state-error');
                this.each(function() {
                    if ($(this).hasClass('date')) {

                            var valdate = checkRegexp($(this), /^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[1-2]\d{3})$/, "date format is wrong, please input as dd/MM/yyyy, e.g. 02/28/2010");
                            if (!valdate) {
                                $(this).val("input in 'dd/mm/yyyy' format");
                            }
                            bValid = bValid && valdate;
                return bValid;

                        }
                }); 

    }});

    function checkRegexp(o, regexp, n) {
        if (!(regexp.test(o.val()))) {
            o.addClass('ui-state-error');
            //updateTips(n);
            return false;
        } else {
            return true;
        }
        }

 })(jQuery);

на ваш взгляд:

  1. добавить class = 'date' в поле ввода
  2. вызвать плагин $("#yourInput").alidateInput();

Решение2: Использовать Jquery UI Date Pick (решение, которое я использую сейчас)

     <script language="javascript" type="text/javascript">
            $(function() {
// use date picker to your textbox input 
                $(".yourInput").datepicker();
                $(".yourInput").datepicker('option', { dateFormat: "dd/mm/yy" });
// disable any human input to the textbox input
                $(".yourInput").keyup(function() {
                    $(this).val("");
                });
            });
        </script>

Подробнее о решении 2: http://www.gregshackles.com/2010/03/templated-helpers-and-custom-model-binders-in-asp-net-mvc-2/

0 голосов
/ 17 августа 2010

Я столкнулся с той же проблемой и не могу найти решение. Я не могу поверить, что все не сталкивались с этой проблемой. Я использовал модуль jquery.maskedinput.js, и он работал отлично, но когда я начал добавлять украшение «[DataType (DataType.Date)]]» с «EditorFor», если назначает ввод даты и времени текстовое поле class = "class =" одна линия". Добавление этого класса нарушает маскированный ввод js. Он также форматирует мои нижние даты как «2/3/1010», что затем создает мою маску jquery «99/99/9999».

...