MVC 3 Custom ValidationAttribute для CheckBox для двойного запуска на стороне клиента - PullRequest
7 голосов
/ 21 февраля 2011

Я собираюсь выложить код, чтобы объяснить всю ситуацию, а затем изложить описание проблемы:

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

 [MustBeTrue(ErrorMessageResourceType = typeof(ErrorMessages), ErrorMessageResourceName = "MustAccept")]
 public bool HasAuthorizedBanking { get; set; }

Как вы можете видеть, я создал собственный атрибут проверки для обработки этого MustBeTrue для обработки флажка, поскольку [Обязательный] равен , в настоящее время не работает для проверки на стороне клиента на флажках в MVC3

public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if ((bool)value)
            return ValidationResult.Success;

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

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "truerequired"
        };

        yield return rule;
    }
}

Затем я добавляю CheckBoxFor с ValidationMessage к своему представлению:

@Html.CheckBoxFor(model => model.HasAuthorizedBanking)
@Html.ValidationMessageFor(model => model.HasAuthorizedBanking, "", new { @class = "validationtext" })  

Для реализации этой клиентской стороны я создал метод валидатора jQuery идобавлен ненавязчивый адаптер:

// Checkbox Validation
jQuery.validator.addMethod("checkrequired", function (value, element) {
    var checked = false;
    checked = $(element).is(':checked');
    return checked;
}, '');

jQuery.validator.unobtrusive.adapters.addBool("truerequired", "checkrequired");

На мой взгляд, все этапы процесса регистрации находятся на одной странице, элементы скрыты и показаны с помощью jQuery и проверены с помощью проверки jQuery.При нажатии кнопки «Далее» каждый элемент ввода на странице запускается для проверки:

 var validator = $("#WizardForm").validate(); // obtain validator
    var anyError = false;
    $step.find("input").each(function () {
        if (!validator.element(this)) { // validate every input element inside this step
            anyError = true;
        }

    });

    if (anyError)
        return false;

Примечания:

  • Существует только одно свойствов моей модели с атрибутом MustBeTrue, и есть только один CheckBoxFor и соответствующий ValidationMessageFor на всей странице.
  • Чтобы отслеживать, когда вызывается этот метод, я просто помещаю предупреждение (флажок);внутри метода jQuery Validator 'checkrequired'.

Проблема: Когда флажок установлен / снят, метод 'checkrequired' запускается один раз.Однако, когда кнопка «Далее» нажата, и мы решили проверить все элементы ввода, она запускается дважды независимо от того, установлен флажок или нет. Интересно, , если он отмечен, первая проверка возвращает true, а вторая возвращает false (это второе ложное возвращение - моя главная проблема - страница не будет проверяться и не позволит вам перейти к следующему шагу.).Кроме того, когда он отмечен и нажат «Далее», сообщение ValidationMessageFor исчезает, как если бы оно было действительным.

Редактировать: У меня есть другой пользовательский атрибут для проверки возраста в текстовом поле jQuery DatePickerхотя он реализован точно таким же образом - он запускается только один раз при тех же условиях.

1 Ответ

4 голосов
/ 22 февраля 2011

Оказывается, проблема в том, что Html.CheckBoxFor генерирует второй элемент ввода с тем же именем, что и у флажка, как описано здесь: http://forums.asp.net/t/1314753.aspx

<input data-val="true" data-val-required="The HasAuthorizedBanking field is required." data-val-truerequired="You must accept to continue." id="bankingtermscheckbox" name="HasAuthorizedBanking" type="checkbox" value="true" />
<input name="HasAuthorizedBanking" type="hidden" value="false" />

Исправление было измененоселектор jQuery для просмотра только тех элементов ввода, тип которых не скрыт:

$step.find(':input:not(:hidden)').each(function () { // Select all input elements except those that are hidden
        if (!validator.element(this)) { // validate every input element inside this step
            anyError = true;
        }

    });

    if (anyError)
        return false; // exit if any error found
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...