Как изменить валидацию сообщения «data-val-number» в MVC, пока оно генерируется помощником @Html - PullRequest
72 голосов
/ 28 января 2011

Предположим, что эта модель:

Public Class Detail
    ...
    <DisplayName("Custom DisplayName")>
    <Required(ErrorMessage:="Custom ErrorMessage")>
    Public Property PercentChange As Integer
    ...
end class

, а представление:

@Html.TextBoxFor(Function(m) m.PercentChange)

продолжит этот HTML:

   <input data-val="true" 
    data-val-number="The field 'Custom DisplayName' must be a number." 
    data-val-required="Custom ErrorMessage"     
    id="PercentChange" 
    name="PercentChange" type="text" value="0" />

Я хочу настроить data-val-number сообщение об ошибке, которое, я думаю, сгенерировано, потому что PercentChange является Integer.Я искал такой атрибут, чтобы изменить его, range или что-то связанное, не работает.
Я знаю, что есть шанс отредактировать сам файл ненавязчивого js или переопределить его на стороне клиента.Я хочу изменить сообщение об ошибке data-val-number, как и другие на стороне сервера.

Ответы [ 13 ]

72 голосов
/ 18 апреля 2013

Вы можете переопределить сообщение, указав атрибут data-val-number при рендеринге поля.Это отменяет сообщение по умолчанию.Это работает по крайней мере с MVC 4.

@Html.EditorFor (model => model.MyNumberField, new {data_val_number = "Введите целое число, чувак!"})

Помните, что вы должны использовать подчеркивание в имени атрибута, чтобы Razor принял ваш атрибут.

49 голосов
/ 23 августа 2013

Что вам нужно сделать, это:

Добавьте следующий код внутри Application_Start() в Global.asax:

 ClientDataTypeModelValidatorProvider.ResourceClassKey = "Messages";
 DefaultModelBinder.ResourceClassKey = "Messages";

Щелкните правой кнопкой мыши ваш проект ASP.NET MVC в VS. Выберите Add => Add ASP.NET Folder => App_GlobalResources.

Добавьте файл .resx с именем Messages.resx в эту папку.

Добавьте эти строковые ресурсы в файл .resx:

FieldMustBeDate        The field {0} must be a date.
FieldMustBeNumeric     The field {0} must be a number.
PropertyValueInvalid   The value '{0}' is not valid for {1}.
PropertyValueRequired  A value is required.

Измените значение FieldMustBeNumeric, как хотите ...:)

Готово.


Проверьте это сообщение для более подробной информации:

Локализация сообщений об ошибках по умолчанию в ASP.NET MVC и WebForms

37 голосов
/ 28 января 2011

Это не будет легко. Сообщение по умолчанию сохраняется как встроенный ресурс в сборке System.Web.Mvc, а извлекаемый метод является закрытым статическим методом внутреннего закрытого внутреннего класса (System.Web.Mvc.ClientDataTypeModelValidatorProvider+NumericModelValidator.MakeErrorString). Как будто парень из Microsoft, который это кодировал, скрывал совершенно секретно :-)

Вы можете взглянуть на следующее сообщение в блоге , в котором описывается возможное решение. В основном вам необходимо заменить существующий ClientDataTypeModelValidatorProvider на пользовательский.

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

22 голосов
/ 11 октября 2011

В качестве альтернативы я применил атрибут RegularExpression, чтобы перехватить недопустимую запись и установить там свое сообщение:

[RegularExpression(@"[0-9]*$", ErrorMessage = "Please enter a valid number ")]

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

РЕДАКТИРОВАТЬ: Это хорошо работало в MVC3, но, кажется, вполне могут быть лучшие решения для MVC4 +.

11 голосов
/ 20 июня 2011

Из этой книги о MVC 3, которая у меня есть. Все, что вам нужно сделать, это:

public class ClientNumberValidatorProvider : ClientDataTypeModelValidatorProvider 
{ 
   public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, 
                                                          ControllerContext context) 
   { 
       bool isNumericField = base.GetValidators(metadata, context).Any(); 
       if (isNumericField) 
           yield return new ClientSideNumberValidator(metadata, context); 
   } 
} 

public class ClientSideNumberValidator : ModelValidator 
{ 
  public ClientSideNumberValidator(ModelMetadata metadata,  
      ControllerContext controllerContext) : base(metadata, controllerContext) { } 

  public override IEnumerable<ModelValidationResult> Validate(object container) 
  { 
     yield break; // Do nothing for server-side validation 
  } 

  public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() 
  { 
     yield return new ModelClientValidationRule { 
        ValidationType = "number", 
        ErrorMessage = string.Format(CultureInfo.CurrentCulture,  
                                     ValidationMessages.MustBeNumber,  
                                     Metadata.GetDisplayName()) 
        }; 
  } 
} 

protected void Application_Start() 
{ 
    // Leave the rest of this method unchanged 

    var existingProvider = ModelValidatorProviders.Providers 
        .Single(x => x is ClientDataTypeModelValidatorProvider); 
    ModelValidatorProviders.Providers.Remove(existingProvider); 
    ModelValidatorProviders.Providers.Add(new ClientNumberValidatorProvider()); 
} 

Обратите внимание, что получено сообщение ErrorMessage, вы указываете текущую культуру, а локализованное сообщение извлекается из файла ресурсов .resx ValidationMessages (здесь это касается особенностей культуры). Если вам это не нужно, просто замените его собственным сообщением.

7 голосов
/ 15 июня 2011

Вот еще одно решение, которое изменяет сторону клиента сообщения без изменения источника MVC3.Полная информация в этом сообщении:

https://greenicicle.wordpress.com/2011/02/28/fixing-non-localizable-validation-messages-with-javascript/

Короче говоря, вам нужно включить следующий скрипт после загрузки проверки jQuery плюс соответствующий файл локализации .

(function ($) {
    // Walk through the adapters that connect unobstrusive validation to jQuery.validate.
    // Look for all adapters that perform number validation
    $.each($.validator.unobtrusive.adapters, function () {
        if (this.name === "number") {
            // Get the method called by the adapter, and replace it with one 
            // that changes the message to the jQuery.validate default message
            // that can be globalized. If that string contains a {0} placeholder, 
            // it is replaced by the field name.
            var baseAdapt = this.adapt;
            this.adapt = function (options) {
                var fieldName = new RegExp("The field (.+) must be a number").exec(options.message)[1];
                options.message = $.validator.format($.validator.messages.number, fieldName);
                baseAdapt(options);
            };
        }
    });
} (jQuery));
4 голосов
/ 02 февраля 2013

Вы можете установить ResourceKey класса ClientDataTypeModelValidatorProvider в качестве имени глобального ресурса, содержащего ключ FieldMustBeNumeric, чтобы заменить сообщение об ошибке проверки mvc числа вашим пользовательским сообщением.Также ключом сообщения об ошибке проверки даты является FieldMustBeDate.

ClientDataTypeModelValidatorProvider.ResourceKey="MyResources"; // MyResource is my global resource
3 голосов
/ 29 января 2014

Вот еще одно решение на чистом js, которое работает, если вы хотите указывать сообщения глобально, а не пользовательские сообщения для каждого элемента.

Ключ в том, что сообщения проверки устанавливаются с использованием jquery.validation.unobtrusive.js с использованием атрибута data-val-xxx для каждого элемента, поэтому все, что вам нужно сделать, это заменить эти сообщения, прежде чем библиотека их использует, это немного грязно, но я просто хотел сделать работу быстро и быстро, поэтому здесь идет проверка типа номера:

    $('[data-val-number]').each(function () {
    var el = $(this);
    var orig = el.data('val-number');

    var fieldName = orig.replace('The field ', '');
    fieldName = fieldName.replace(' must be a number.', '');

    el.attr('data-val-number', fieldName + ' باید عددی باشد')
});

хорошо то, что он не требует компиляции, и вы можете легко расширить его позже, хотя и не надежно, но быстро.

2 голосов
/ 03 февраля 2015

Проверьте это тоже:

Полное руководство по проверке в ASP.NET MVC 3 - Часть 2

Основные части статьи следуют (вставлено в копию)).

Создание полнофункционального пользовательского валидатора, работающего как на клиенте, так и на сервере, состоит из четырех отдельных частей.Сначала мы создаем подкласс ValidationAttribute и добавляем нашу логику проверки на стороне сервера.Затем мы реализуем IClientValidatable в нашем атрибуте, чтобы позволить атрибутам HTML5 data-* передаваться клиенту.В-третьих, мы пишем пользовательскую функцию JavaScript, которая выполняет проверку на клиенте.Наконец, мы создаем адаптер для преобразования атрибутов HTML5 в формат, понятный нашей пользовательской функции.Хотя это звучит как большая работа, как только вы начнете, вы найдете это относительно просто.

Подклассификация ValidationAttribute

В этом примере мы напишемСредство проверки NotEqualTo, которое просто проверяет, что значение одного свойства не равно значению другого.

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class NotEqualToAttribute : ValidationAttribute
{
    private const string DefaultErrorMessage = "{0} cannot be the same as {1}.";

    public string OtherProperty { get; private set; }

    public NotEqualToAttribute(string otherProperty)
        : base(DefaultErrorMessage)
    {
        if (string.IsNullOrEmpty(otherProperty))
        {
            throw new ArgumentNullException("otherProperty");
        }

        OtherProperty = otherProperty;
    }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(ErrorMessageString, name, OtherProperty);
    }

    protected override ValidationResult IsValid(object value, 
        ValidationContext validationContext)
    {
        if (value != null)
        {
            var otherProperty = validationContext.ObjectInstance.GetType()
                .GetProperty(OtherProperty);

            var otherPropertyValue = otherProperty
                .GetValue(validationContext.ObjectInstance, null);

            if (value.Equals(otherPropertyValue))
            {
                return new ValidationResult(
                    FormatErrorMessage(validationContext.DisplayName));
            }
        }
    return ValidationResult.Success;
    }        
}

Добавьте новый атрибут в свойство пароля в RegisterModel и запустите приложение.

[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
[NotEqualTo("UserName")]
public string Password { get; set; }
...

Реализация IClientValidatable

В ASP.NET MVC 2 был механизм для добавления проверки на стороне клиента, но он был не очень хорош.К счастью, в MVC 3 все улучшилось, и процесс теперь довольно тривиален, и, к счастью, не включает в себя изменение Global.asax, как в предыдущей версии.

Первый шаг для вашего пользовательскогоАтрибут проверки для реализации IClientValidatable.Это простой интерфейс с одним методом:

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

    clientValidationRule.ValidationParameters.Add("otherproperty", OtherProperty);

    return new[] { clientValidationRule };
}

Если вы запустите приложение сейчас и просмотрите исходный код, вы увидите, что html для ввода пароля теперь содержит ваши notequalto атрибуты данных:

<div class="editor-field">
    <input data-val="true" data-val-notequalto="Password cannot be the same as UserName." 
    data-val-notequalto-otherproperty="UserName" 
    data-val-regex="Weak password detected." 
    data-val-regex-pattern="^(?!password$)(?!12345$).*" 
    data-val-required="The Password field is required." 
    id="Password" name="Password" type="password" />
    <span class="hint">Enter your password here</span>
    <span class="field-validation-valid" data-valmsg-for="Password" 
    data-valmsg-replace="true"></span>
</div>

Создание пользовательской функции проверки jQuery

Весь этот код лучше всего помещать в отдельный файл JavaScript.

(function ($) {
    $.validator.addMethod("notequalto", function (value, element, params) {
        if (!this.optional(element)) {
            var otherProp = $('#' + params);
            return (otherProp.val() != 
        }
    return true;
});

$.validator.unobtrusive.adapters.addSingleVal("notequalto", "otherproperty");

}(jQuery));

В зависимости от вашей проверкитребования, вы можете обнаружить, что библиотека jquery.validate уже имеет код, необходимый для самой проверки.В jquery.validate есть много валидаторов, которые не были реализованы или сопоставлены с аннотациями данных, поэтому, если они удовлетворяют вашим потребностям, все, что вам нужно написать в javascript, - это адаптер или даже вызов встроенного адаптера, который можетбыть всего лишь одной строкой.Загляните внутрь jquery.validate.js , чтобы узнать, что доступно.

Использование существующего адаптера jquery.validate.unobtrusive

Работа адаптера заключается в чтении атрибутов HTML5 data-* в элементе формы и преобразовании этих данных в форму, понятную для jquery.validate и вашей пользовательской функции проверки.Вы не обязаны выполнять всю работу самостоятельно, хотя во многих случаях вы можете вызвать встроенный адаптер.jquery.validate.unobtrusive объявляет три встроенных адаптера, которые могут использоваться в большинстве ситуаций.Это:

jQuery.validator.unobtrusive.adapters.addBool - used when your validator does not need any additional data.
jQuery.validator.unobtrusive.adapters.addSingleVal - used when your validator takes in one piece of additional data.
jQuery.validator.unobtrusive.adapters.addMinMax - used when your validator deals with minimum and maximum values such as range or string length.

Если ваш валидатор не входит ни в одну из этих категорий, вы должны написать свой собственный адаптер, используя метод jQuery.validator.unobtrusive.adapters.add.Это не так сложно, как кажется, и мы увидим пример позже в этой статье.

Мы используем метод addSingleVal, передавая имя адаптера и имя единственного значения, которое мыхочу пройти.Если имя функции проверки отличается от адаптера, вы можете передать третий параметр (ruleName):

jQuery.validator.unobtrusive.adapters.addSingleVal("notequalto", "otherproperty", "mynotequaltofunction");

На этом этапе наш пользовательский валидатор завершен.

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

HTH.

1 голос
/ 27 июля 2014

Или вы можете просто сделать это.

@Html.ValidationMessageFor(m => m.PercentChange, "Custom Message: Input value must be a number"), new { @style = "display:none" })

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...