ASP.Net MVC 3 - ненавязчивая проверка на стороне клиента для шаблонов редактора - PullRequest
7 голосов
/ 21 марта 2011

Я новичок в ASP.Net MVC 3, столкнулся с некоторыми проблемами при попытке реализовать ненавязчивую проверку на стороне клиента для шаблона редактора, который я создал для отображения даты в произвольном порядке.

UI
Мне нужно показать дату в трех текстовом интерфейсе в формате

enter image description here

Я выставил EditorTemplate для отображения даты в трех частях как

@model DateTime?

<table class="datetime">
<tr>
    <td>@Html.TextBox("Day", (Model.HasValue ? Model.Value.ToString("dd") : string.Empty)) </td>
    <td class="separator">/</td>
    <td>@Html.TextBox("Month", (Model.HasValue ? Model.Value.ToString("MM") : string.Empty))</td>
    <td class="separator">/</td>
    <td>@Html.TextBox("Year", (Model.HasValue ? Model.Value.ToString("yyyy") : string.Empty))</td>
</tr>
<tr>
    <td class="label">dd</td>
    <td/>
    <td class="label">mm</td>
    <td/>
    <td class="label">yyyy</td>
</tr>
</table>

Модель Я должен связать поле Date of Birth, которое является свойством в подобъекте моей модели, с этим свойством, в этой структуре

MyModel
    --> MySubModel
          --> DateOfBirth

public class MySubModel
{
    ...

    [DataType(DataType.Date)]
    [Display(Name = "Date of birth")]
    [DateTimeClientValidation()]
    public DateTime DateofBirth { get; set; }

    ...
}

Проверка на стороне клиента

Я создал пользовательский атрибут проверки, который реализует IClientValidatable как

public class DateTimeClientValidationAttribute : ValidationAttribute, IClientValidatable
{
    ...

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        List<ModelClientValidationRule> clientRules = new List<ModelClientValidationRule>();

        //Combined date should be valid
        ModelClientValidationRule validDateRule = new ModelClientValidationRule
        {
            ErrorMessage = "Please enter a valid date.",
            ValidationType = "validdate"
        };
        validDateRule.ValidationParameters.Add("dayelement", metadata.PropertyName + ".Day");
        validDateRule.ValidationParameters.Add("monthelement", metadata.PropertyName + ".Month");
        validDateRule.ValidationParameters.Add("yearelement", metadata.PropertyName + ".Year");
        clientRules.Add(validDateRule);

        return clientRules;
    }
    ...
}

Я пытаюсь передать имена элементов текстовых полей Day, Month & Year здесь элементам проверки на стороне клиента, поэтомупозже я напишу метод проверки подлинности jquery и адаптер на стороне клиента, которые будут использовать эти элементы и выполнять проверку на стороне клиента.

View Теперь, чтобы использовать этот шаблон редактора, я вставил Представление в следующие строки

@model MyModel
...
<tr>
    <td class="editor-label">
        @Html.LabelFor(m => m.MySubModel.DateofBirth)
    </td>
    <td class="editor-field">
        @Html.EditorFor(m => m.MySubModel.DateofBirth)
        @Html.ValidationMessageFor(m => m.MySubModel.DateofBirth)
    </td>
</tr>
...

Добавил все соответствующие файлы проверки jquery в представлении в качестве ссылок

Вопросы

  1. Это не выводит ненавязчивые атрибуты проверки JavaScript в html, хотя я реализовал IClientValidatable .В целях тестирования, когда я помещаю тот же атрибут ( DateTimeClientValidation ) в другое свойство в модели, которая не использует этот шаблон редактора, он выводит эти атрибуты проверки, он не выводит его только для этого редактора.шаблон.Где я мог ошибиться?
  2. Относительно диапазона сообщения проверки для шаблона редактора, правильно ли, что я помещаю его только в представление или я должен поместить его непосредственно в шаблон редактора (@Html.ValidationMessageFor(m => m.MySubModel.DateofBirth) )
  3. В этом примере я прав в дизайне, я вставил DateTimeClientValidationAttribute , который на самом деле является атрибутом, который я поставилна модели, но этот компонент немного знает об интерфейсе пользователя (так как он пытается выдать клиенту имя элемента Day, Month & Year), это делает Model немного знакомым с View, нарушаю ли я какие-либо принципы проектирования здесь?
  4. В DateTimeClientValidationAttribute я пытаюсь передать клиенту имена элементов дня, месяца и года, чтобы клиентский скрипт мог выполнить проверки на нем.Но поскольку свойство модели DateofBirth находится в подобъекте, фактическое имя элемента в скрипте равно MySubObject.DateOfBirth , что делает имя текстового поля Day равным MySubObject.DateofBirth.День , как мне найти это полное имя модели в методе GetClientValidationRules , чтобы я мог передать имя клиенту?

Спасибо за терпениезачитать все это и за ответы

Ответы [ 2 ]

10 голосов
/ 06 апреля 2011

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

Первое, что нужно сделать, это задать элемент управления как

@model DateTime?

<table class="datetime">
<tr>
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("dd") : string.Empty)) </td>
    <td class="separator">/</td>
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("MM") : string.Empty))</td>
    <td class="separator">/</td>
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("yyyy") : string.Empty))</td>
</tr>
<tr>
    <td class="label">dd</td>
    <td/>
    <td class="label">mm</td>
    <td/>
    <td class="label">yyyy</td>
</tr>
</table>

Убедитесь, что вы указали пустые строки в качестве имени для всех трех текстовых полей, это заставляет инфраструктуру MVC генерировать одинаковое имя , соответствующее Model DateofBirth для всех трехтекстовые поля на стороне клиента.Кроме того, ненавязчивые параметры проверки javascript будут сгенерированы для первого текстового поля в списке, поскольку это первый случай элемента управления для редактирования с именем модели.

На стороне клиента, при любом событии в любомиз этих текстовых полей запускаются все соответствующие события проверки, так как все эти 3 текстовых поля имеют одно и то же имя.

Поверх обычных проверок, как требуется, .... мы должны написать собственную процедуру проверки клиента, которая быобъединить все эти три значения и проверить, образует ли объединенное значение действительную дату.Это может быть достигнуто как в ответе , заданном Джеффом .

5 голосов
/ 01 апреля 2011

Хорошо, так несколько вещей.Первый - если это вообще возможно, не разбивайте дату на три поля.Вы избавите себя от головной боли, просто настроив его как отдельное поле с некоторой проверкой и, возможно, с помощью DatePicker jQueryUI.

Далее, в своем пользовательском коде атрибута внутри DateTimeClientValidationAttribute, вы никогда не проверяете, действительно лидата действительна при реализации IsValid:

protected override ValidationResult IsValid(object value, 
    ValidationContext validationContext) 
{
   ...
   // Put date parts together and check is valid...
   if (DateTime.TryParse(year+"/"+month+"/"+day, out dateResult))
      return ValidationResult.Success;

   // Not valid
   return new ValidationResult(String.Format(ErrorMessageString, 
      validationContext.DisplayName));
}

Далее вам нужно будет создать ненавязчивый адаптер проверки и метод проверки jQuery, который собирает параметры вместе и пытается проанализировать дату:

jQuery.validator.unobtrusive.adapters.add(
    'validdate', // notice this is coming from how you named your validation rule
    ['dayelement'],
    ['monthelement'],
    ['yearelement']
    function (options) {
        options.rules['datepartcheck'] = options.params;
        options.messages['datepartcheck'] = options.message;
    }
);
jQuery.validator.addMethod('datepartcheck', function (value, element, params) {
    var year = params[2];
    var month = params[1];
    var day = params[0];

    var birthDate = year + '/' + month-1 + '/' + day;
    var isValid = true;

    try {
        // datepicker is a part of jqueryUI.
        // include it and you can take advantage of .parseDate:
        $.datepicker.parseDate('yy/mm/dd', birthDate);
    }
    catch (error) {
        isValid = false;
    }
    return isValid;
}, '');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...