Подтвердить что ты не робот

Как изменить валидность сообщения "валид-число" в MVC, когда он сгенерирован помощником @Html

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

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, как и другие на стороне сервера.

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

Добавьте следующий код внутри 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

Ответ 4

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

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

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

EDIT: это хорошо работает в MVC3, но кажется, что для MVC4 + могут быть лучшие решения.

Ответ 5

Из этой книги о 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, вы указываете текущую культуру, и локализованное сообщение извлекается из файла ValidationMessages (в данном случае - для культуры).resx. Если вам это не нужно, просто замените его своим собственным сообщением.

Ответ 6

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

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

Вкратце, что вам нужно сделать, это включить следующий script после загрузки проверки 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));

Ответ 7

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

ClientDataTypeModelValidatorProvider.ResourceKey="MyResources"; // MyResource is my global resource

Ответ 8

Вот еще одно решение в чистом 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 + ' باید عددی باشد')
});

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

Ответ 9

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

Полное руководство для проверки в 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");

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

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

НТН.

Ответ 10

Я просто сделал это, а затем использовал выражение регулярного выражения:

$(document).ready(function () {
    $.validator.methods.number = function (e) {
        return true;
    };
});


[RegularExpression(@"^[0-9\.]*$", ErrorMessage = "Invalid Amount")]
public decimal? Amount { get; set; }

Ответ 11

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

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

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

Ответ 12

У меня есть эта проблема в KendoGrid, я использую script в END View для переопределения данных-val-number:

@(Html.Kendo().Grid<Test.ViewModel>(Model)
  .Name("listado")
  ...
  .Columns(columns =>
    {
        columns.Bound("idElementColumn").Filterable(false);
    ...
    }

И по крайней мере, в конце View я положил:

<script type="text/javascript">
        $("#listado").on("click", function (e) {
            $(".k-grid #idElementColumn").attr('data-val-number', 'Ingrese un número.');
        });    
</script>