MVC2 Проверка на стороне клиента для DateTime?
Какой подход вы рекомендуете для проверки 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 ответа
Как указано выше, следуйте посту Фила Хаака о пользовательских проверках: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
Вот как бы я это сделал:
- Добавьте класс 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);
}
});
Это должно охватывать вещи...
Джош,
Ваша проблема - довольно распространенная проблема в MVC, которая заключается в том, что связыватель модели пытается связать введенные значения из формы в модель. очевидно, если он не "подходит", вы сразу же получите ошибку.
так как мне сделать так, чтобы связыватель моделей использовал мою пользовательскую проверку? и вернуть мое сообщение об ошибке?
ну, сначала прочитайте и сделайте вещи, написанные Филом Хааком. тогда у вас есть пользовательская проверка.
следующая вещь. Не используйте целые числа и даты в вашей модели! Если пользователь может ввести все, что он хочет, в текстовое поле, это всегда будет создавать проблемы.
то, что вы должны сделать, это создать flatObject вашего объекта.
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; }
}
}
единственные целые числа, которые у меня есть, из выпадающих списков, потому что они не терпят неудачу, если значения в выпадающих списках являются целыми дата (дата) является строкой. я делаю пользовательскую проверку для этой строки. связыватель моделей связывается с этим объектом FlatNieuw.
мой класс Nieuw имеет точно такие же имена полей, что и этот класс. поэтому, когда вы используете UpdateModel(), это все еще работает. если вы делаете новую запись, вы можете использовать automapper, чтобы отобразить этот flatObject на ваш обычный объект.
Я думаю, что это, вместе с блогом Фила Хаака, должно помочь вам в этом. Если у вас есть вопросы, не стесняйтесь спрашивать.
Согласно моему опыту, иногда проверки 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);
на ваш взгляд:
- добавить class='date' в поле ввода
- вызвать плагин
$("#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/
Я сталкиваюсь с той же проблемой и не могу найти решение. Я не могу поверить, что все не сталкивались с этой проблемой. Я использовал модуль jquery.maskedinput.js, и он работал отлично, но когда я начал добавлять украшение "[DataType(DataType.Date)]]" с "EditorFor", если назначает ввод даты и времени класс class="text-box одна линия". Добавление этого класса нарушает маскированный ввод js. Он также форматирует мои нижние даты как "2/3/1010", что затем создает мою маску jquery "99/99/9999".