Проверка на стороне клиента не запускается для CompareAttribute DataAnnotation - PullRequest
5 голосов
/ 15 января 2011

Я выкладываю представление, которое сравнивает две строки пароля. Два свойства в одной из моих моделей довольно просты:

    [Required]
    [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")]
    [StringLength(20, MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "New Password")]
    public string NewPassword { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")]
    [StringLength(20, MinimumLength = 6)]
    [Display(Name = "Confirm Password")]
    [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }

Вот мой код просмотра:

<table class="fieldset center" width="400">
    <tbody>
        <tr>
            <th width="150">
                @Html.LabelFor(m => m.NewPassword)
            </th>
            <td>
                @Html.PasswordFor(m => m.NewPassword, new { @class = "itext3" })
                <br /><br />@Html.ValidationMessageFor(m => m.NewPassword)
            </td>
        </tr>                       
        <tr>
            <th width="150">
                @Html.LabelFor(m => m.ConfirmPassword)
            </th>
            <td>
                @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "itext3" })
                <br /><br />@Html.ValidationMessageFor(m => m.ConfirmPassword)
            </td>
        </tr>
    </tbody>
</table>

Все атрибуты запускают свои сообщения проверки на стороне клиента при тестировании, за исключением атрибута CompareAttribute для ConfirmPassword, который не запускается, пока я не попаду на сервер. Однако в моем контроллере ModelState.IsValid = false.

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

Я использую MVC 3 RTM.

Ответы [ 4 ]

8 голосов
/ 27 июля 2011

В jquery.validate.unobtrusive.js есть ошибка (и jquery.validate.unobtrusive.min.js, минимизированная версия). Проверка на стороне клиента, передаваемая в результате атрибута [Compare], будет работать ТОЛЬКО в том случае, если поле сравнения является ПЕРВЫМ полем в форме. Чтобы исправить эту ошибку, найдите эту строку в jquery.validate.unobtrusive.js:

element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];

, что приводит к этому эквиваленту:

element = $(options.form).find(":input[name=MyExample.Control]")[0];

К сожалению, это неправильный синтаксис для find (), и он ссылается на первый элемент управления вводом в форме.

Измените эту строку на:

element = $(options.form).find(":input[name='" + fullOtherName + "']")[0];

, что приводит к этому эквиваленту:

element = $(options.form).find(":input[name='MyExample.Control]'")[0];

Какой синтаксис правильный и правильно сопоставляет элемент управления вводом с указанным именем.

Найдите тот же блок кода в jquery.validate.unobtrusive.min.js, который выглядит следующим образом:

f=a(b.form).find(":input[name="+d+"]")[0];

и измените его на:

f=a(b.form).find(":input[name='"+d+"']")[0];
4 голосов
/ 27 января 2011

Посмотрите на теги вашего скрипта в вашем _Layout.cshtml.Я предполагаю, что проблема, вероятно, ваши ссылки jQuery.Вы начали проект MVC 3 с нуля, или вы используете пример проекта или что-то в этом роде?

Вот что случилось со мной;У меня были похожие проблемы ...

  • Я использовал пример кода, который указывал на ajax.microsoft.com в атрибутах src
  • Так, например, один из тегов скрипта выгляделкак это: <script src="http://ajax.microsoft.com/ajax/jquery.validate/1.7/jquery.validate.min.js"></script>
  • Я хотел лучше понять, что js выполнял на стороне клиента, поэтому я изменил это на следующее: <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
  • Это просто пример,Я думаю, что есть еще пара тегов сценария, которые я также изменил

Итак, после перехода на файлы jQuery с внутренним обслуживанием все заработало.Я вернулся и посмотрел на мой локальный файл .validate.js ... и это была версия 1.6.Вот как я понял, что проблема была связана с версией jQuery или его совместимостью с одной из других js-библиотек.

Суть в том, что похоже, что 1.7 не полностью работает с валидатором.unobtrusive.js lib, который у меня был ... может быть, есть более новая версия, которая работает с 1.7 ... как я уже говорил, я возился с примером проекта, поэтому там есть некоторые неизвестные.Я полагаю, что это также может быть несовместимость с библиотекой MvcValidation.js между ней и одной из других библиотек js тоже?

В любом случае, я бы сказал, что самый простой способ заявить о вашей проблеме - это то, что выскорее всего, ссылаясь на плохую комбинацию js libs.Я бы сказал, что лучший отказоустойчивый способ получить хорошую комбинацию js libs - это создать новый проект Asp.Net MVC 3 в Visual Studio и посмотреть, какие версии он предоставляет вам по умолчанию / с шаблоном проекта ... при условии, чточто вы не начали проект с нуля.Если вы ДЕЙСТВИТЕЛЬНО запускали его с нуля, то, возможно, вы изменили файл макета, чтобы иметь плохие ссылки на js, или если ничего из этого не является правдой, то я полагаю, что это может быть проблемой с шаблонами проекта VisualStudio? ... реально я бы сказал,сомнительно, хотя.Все это говорит - я бы сказал, что наиболее вероятная причина [на которую я бы поставил в любом случае] состоит в том, что вы просто попали в беду, как я, пытаясь быстро использовать некоторый пример кода =)

1 голос
/ 15 февраля 2012

Мне так и не удалось сделать способ работы по умолчанию.Похоже, что в JQuery он запускает только те методы проверки, которые зарегистрированы в JQuery.validator.

Первоначально я делал что-то вроде этого ...

jQuery.validator.unobtrusive.adapters.add("equaltopropertyvalidation", ["param"], function (rule)
    {
        alert("attaching custom validation adapter.");
        rule.rules["equaltopropertyvalidation"] = rule.params.param;
        rule.messages["equaltopropertyvalidation"] = rule.message;

        return function (value, element, param)
        {
           alert("now validating!");
           return value == this.currentForm[param].value;
        };
    });

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

Хорошо, потратив много времени, чтобы выяснить, в чем делоЯ реализовал это так, как предлагает эта статья, и это работает.Теперь это так, и это работает.

<script type="text/javascript">

    jQuery.validator.addMethod("equaltopropertyvalidation", function (value, element, param)
    {
        return value == this.currentForm[param].value;
    });

    jQuery.validator.unobtrusive.adapters.add("equaltopropertyvalidation", ["param"], function (rule)
    {
        rule.rules["equaltopropertyvalidation"] = rule.params.param;
        rule.messages["equaltopropertyvalidation"] = rule.message;
    });

</script>

Если вам нравятся подробности, то вот оно: посмотрите в jquery.validate.js и найдите

      check: function (element)

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

      var rules = $(element).rules();

Затем он перебирает коллекцию правил, создает элемент правила для каждого элемента в коллекции и затем пытается найти соответствующий метод для запуска этого правила.Как только метод найден, он запускается.Для этого используется следующий код.

      var result = $.validator.methods[method].call(this, element.value.replace(/\r/g, ""), element, rule.parameters);

Теперь важно то, что если ваш пользовательский метод не будет добавлен в коллекцию $ .validator.methods с использованием JQuery.validator.addMethod, ЭТО НЕ БУДЕТ НАЙДЕНО, даже если он находится там, в коллекции JQuery.validator.unobtrusive.adapters.

Может быть способ выполнить эту работу без использования JQuery.validator.addMethod (и если да, то кто-нибудь, пожалуйста, уточните)но я полагаю, именно поэтому второй подход работает, а первый - нет.

Я использовал следующие версии файлов Jquery

  1. JQuery: 1.6 / 1.7.1
  2. Jquery.Validate: 1.9.0
  3. JQuery.Unobtrusive.Validate: взято из Microsoft CDN 2/14/2012.
1 голос
/ 15 января 2011

Я протестировал это с ASP.NET MVC 3 RTM, и он отлично работал для меня:

Модель:

public class MyViewModel
{
    [Required]
    [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")]
    [StringLength(20, MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "New Password")]
    public string NewPassword { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")]
    [StringLength(20, MinimumLength = 6)]
    [Display(Name = "Confirm Password")]
    [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

Контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

Представление:

@model SomeAppName.Models.MyViewModel
@{
    ViewBag.Title = "Home Page";
}
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm())
{
    @Html.LabelFor(m => m.NewPassword)
    @Html.PasswordFor(m => m.NewPassword)
    @Html.ValidationMessageFor(m => m.NewPassword)
    <br/>

    @Html.LabelFor(m => m.ConfirmPassword)
    @Html.PasswordFor(m => m.ConfirmPassword)
    @Html.ValidationMessageFor(m => m.ConfirmPassword)

    <br/>
    <input type="submit" value="OK" />
}

В этой конфигурации проверка на стороне клиента прекрасно работает для всех атрибутов, включая [Compare].

...