mvc3 проверить ввод «не равно»

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

Как я могу расширить ненавязчивую проверку, чтобы справиться с этим? Форма не должна быть действительной, если ввод имени равен «Пожалуйста, введите ваше имя...».

Я начал читать запись блога Брэда Уилсона об адаптерах проверки, но я не уверен, что это правильный путь? Мне нужно иметь возможность проверять разные значения по умолчанию в зависимости от поля.

Спасибо


person BZink    schedule 20.04.2011    source источник
comment
В качестве альтернативы рассмотрите возможность использования атрибута заполнителя для отображения текста инструкции, например «Пожалуйста, введите свое имя...», в качестве более удобного UX, а также совместимого со стандартами HTML5 способа дать подсказку пользователю.   -  person KyleMit    schedule 21.02.2017


Ответы (6)


Да, это правильный путь. Вы должны реализовать свой собственный атрибут и реализовать IClientValidatable.

Вы также можете изначально установить обязательное логическое значение false в качестве скрытого поля формы. Когда пользователь изменяет текстовое поле, установите для него значение true.

person Daniel A. White    schedule 20.04.2011

Вот пример, иллюстрирующий, как можно приступить к реализации пользовательского атрибута проверки:

public class NotEqualAttribute : ValidationAttribute, IClientValidatable
{
    public string OtherProperty { get; private set; }
    public NotEqualAttribute(string otherProperty)
    {
        OtherProperty = otherProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(OtherProperty);
        if (property == null)
        {
            return new ValidationResult(
                string.Format(
                    CultureInfo.CurrentCulture, 
                    "{0} is unknown property", 
                    OtherProperty
                )
            );
        }
        var otherValue = property.GetValue(validationContext.ObjectInstance, null);
        if (object.Equals(value, otherValue))
        {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = ErrorMessage,
            ValidationType = "notequalto",
        };
        rule.ValidationParameters["other"] = OtherProperty;
        yield return rule;
    }
}

а потом на модели:

public class MyViewModel
{
    public string Prop1 { get; set; }

    [NotEqual("Prop1", ErrorMessage = "should be different than Prop1")]
    public string Prop2 { get; set; }
}

контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel
        {
            Prop1 = "foo",
            Prop2 = "foo"
        });
    }

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

и просмотр:

@model MyViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
    jQuery.validator.unobtrusive.adapters.add(
        'notequalto', ['other'], function (options) {
            options.rules['notEqualTo'] = '#' + options.params.other;
            if (options.message) {
                options.messages['notEqualTo'] = options.message;
            }
    });

    jQuery.validator.addMethod('notEqualTo', function(value, element, param) {
        return this.optional(element) || value != $(param).val();
    }, '');
</script>

@using (Html.BeginForm())
{
    <div>
        @Html.LabelFor(x => x.Prop1)
        @Html.EditorFor(x => x.Prop1)
        @Html.ValidationMessageFor(x => x.Prop1)
    </div>
    <div>
        @Html.LabelFor(x => x.Prop2)
        @Html.EditorFor(x => x.Prop2)
        @Html.ValidationMessageFor(x => x.Prop2)
    </div>
    <input type="submit" value="OK" />
}
person Darin Dimitrov    schedule 21.04.2011
comment
Работает как шарм, но предоставленное вами решение не может использовать ErrorMessageResourceType и ErrorMessageResourceName. Вы можете использовать что-то вроде: errorMessage = new ResourceManager(ErrorMessageResourceType).GetString(ErrorMessageResourceName); - person Rookian; 06.02.2013
comment
Отличный ответ, очень помог мне встать на правильный путь, чтобы сделать несколько пользовательских валидаторов. - person Etch; 02.11.2013
comment
Мне любопытно, как использовать сообщение об ошибке из ресурса. То, что сказал Рукиан, не является постоянным выражением, поэтому его нельзя использовать в атрибуте. Это решение devtrends.co.uk/blog/ работает с сообщением об ошибке ресурса, но я не вижу разницы. Я думаю, что сообщение о просмотре не подключено правильно? - person Dave; 13.03.2014
comment
он работает с EditorFor, но не с DropDownList. он не генерирует сообщения проверки данных. есть идеи, что мне делать? - person Daniel B; 11.06.2016

Вы можете заставить свою ViewModel реализовать IValidatableObject и при реализации метода Validate (из IValidatableObject) добавить некоторую логику для проверки значений свойств, например.

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
        var results = new List<ValidationResult>();

        if (Name == "Please enter your name...") 
            results.Add(new ValidationResult("You must enter a name");

        ...
        Enter other validation here
        ...     

        return results;
    }

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

person Rich Whitfield    schedule 21.04.2011

Прошло некоторое время с тех пор, как был задан ваш вопрос, но если вам все еще нравятся аннотации данных, эту проблему можно легко решить с помощью этого библиотека:

[Required]
[AssertThat("FieldA != 'some text'")]
public string FieldA { get; set; }

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

[AssertThat("FieldA != FieldB")]

... и когда регистр сравниваемых строк не имеет значения:

[AssertThat("CompareOrdinalIgnoreCase(FieldA, FieldB) != 0")]
person jwaliszko    schedule 17.07.2014

Чтобы немного улучшить ответ @Darin Dimitrov, если вы хотите добавить сообщения из ресурсов, используя ErrorMessageResourceName and ErrorMessageResourceType, просто добавьте это в сообщение об ошибке ErrorMessage = ErrorMessage ?? ErrorMessageString

ErrorMessageString будет искать локализованную версию сообщения об ошибке, которую вы задали в модели, используя эти параметры (ErrorMessageResourceName и ErrorMessageResourceType).

person Query    schedule 18.01.2016

Идеальным решением является настраиваемый атрибут, в котором вы указываете минимальную и максимальную длину, а также MustNotContain="Пожалуйста, введите ваше имя...".

person Leons    schedule 20.04.2011
comment
Я действительно не понимаю, как этот ответ имеет какое-либо отношение к тому, что здесь задают, а именно к тому, как проверить, что два свойства в модели представления не равны. - person Darin Dimitrov; 21.04.2011
comment
Я прочитал вопрос как «Как узнать, что поле «Имя» содержит действительное имя, а не значение по умолчанию «Пожалуйста, введите свое имя». Проверка такого рода может быть выполнена с очень общим атрибутом, который можно использовать во многих полях. - person Leons; 21.04.2011