Как изменить проверку сообщения "data-val-number" в 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-файл unobtrusive или переопределить его на стороне клиента. Я хочу измениться 'ы сообщение, как и другие на стороне сервера.
13 ответов
это будет нелегко. Сообщение по умолчанию сохраняется как встроенный ресурс в System.Web.Mvc
сборка и метод, который извлекается, является частным статическим методом внутреннего запечатанного внутреннего класса (System.Web.Mvc.ClientDataTypeModelValidatorProvider+NumericModelValidator.MakeErrorString
). Это как если бы парень в Microsoft coding это скрывал совершенно секретно: -)
Вы можете взглянуть на следующее блоге который описывает возможное решение. Вам в основном нужно заменить существующий ClientDataTypeModelValidatorProvider заказной.
Если вам не нравится жесткое кодирование, которое вам нужно будет сделать, вы также можете заменить это целочисленное значение внутри модели представления строкой и иметь пользовательский атрибут проверки, который будет выполнять синтаксический анализ и предоставлять пользовательское сообщение об ошибке (которое может быть даже локализовано).
вы можете переопределить сообщение, указав data-val-number атрибутируйте себя при рендеринге поля. Это переопределяет сообщение по умолчанию. Это работает по крайней мере с MVC 4.
@HTML-код.В(модели => модели.MyNumberField, new { data_val_number= " поставь целое число, чувак!"})
помните, что вы должны использовать подчеркивание в имени атрибута для Razor, чтобы принять ваш атрибут.
то, что вы должны сделать, это:
добавьте следующий код внутри Application_Start()
на Global.asax
:
ClientDataTypeModelValidatorProvider.ResourceClassKey = "Messages";
DefaultModelBinder.ResourceClassKey = "Messages";
щелкните правой кнопкой мыши ASP.NET проект MVC в VS. Выберите Add => Add ASP.NET Folder => App_GlobalResources
.
добавить под названием Messages.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
как альтернативный способ обойти это, я применил атрибут RegularExpression, чтобы поймать недопустимую запись и установить там мое сообщение:
[RegularExpression(@"[0-9]*$", ErrorMessage = "Please enter a valid number ")]
это немного хак, но это казалось предпочтительнее сложности других решений, представленных, по крайней мере, в моей конкретной ситуации.
EDIT: это хорошо работало в MVC3, но кажется, что могут быть лучшие решения для MVC4+.
из этой книги на 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 файл. Если вам это не нужно, просто замените его своим собственным сообщением.
вот еще одно решение, которое изменяет клиентскую сторону сообщения без изменения источника MVC3. Полная информация в этом блоге:
короче говоря, вам нужно включить следующий скрипт после загрузки проверки 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));
можно задать ResourceKey класса ClientDataTypeModelValidatorProvider имя глобального ресурса, содержащего FieldMustBeNumeric ключ для замены сообщения об ошибке проверки MVC номер с пользовательским сообщением. Также ключом сообщения об ошибке проверки даты является FieldMustBeDate.
ClientDataTypeModelValidatorProvider.ResourceKey="MyResources"; // MyResource is my global resource
вот еще одно решение в pure 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 + ' باید عددی باشد')
});
хорошо, что он не требует компиляции, и вы можете легко расширить его позже, не надежный, но быстрый.
проверьте это тоже:
Полное руководство по проверке в 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 есть много валидаторов.проверьте, что не были реализованы или сопоставлены с аннотациями данных, поэтому, если они отвечают вашим потребностям, то все, что вам нужно написать в javascript, - это адаптер или даже вызов встроенного адаптера, который может быть как можно меньше одной строкой. Загляни внутрь С помощью jQuery.утверждать.js чтобы узнать, что доступно.
использование существующего jquery.утверждать.ненавязчивый адаптер
задача адаптера-прочитать HTML5 data-*
атрибуты на вашем элементе формы и преобразуют эти данные в форму, которая может быть понята jquery.проверка и пользовательская функция проверки. Вы не обязаны делать ВСЮ работу самостоятельно, хотя и во многих случаях вы можете назвать встроенный адаптер. на jQuery.утверждать.ненавязчивый объявляет три встроенных адаптера, которые можно использовать в большинстве ситуаций. Это:
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.
Я просто сделал это, а затем использовал выражение regex:
$(document).ready(function () {
$.validator.methods.number = function (e) {
return true;
};
});
[RegularExpression(@"^[0-9\.]*$", ErrorMessage = "Invalid Amount")]
public decimal? Amount { get; set; }
или вы можете просто сделать это.
@Html.ValidationMessageFor(m => m.PercentChange, "Custom Message: Input value must be a number"), new { @style = "display:none" })
надеюсь, что это помогает.
у меня есть эта проблема в KendoGrid, я использую скрипт в конце представления для переопределения data-val-number:
@(Html.Kendo().Grid<Test.ViewModel>(Model)
.Name("listado")
...
.Columns(columns =>
{
columns.Bound("idElementColumn").Filterable(false);
...
}
и, по крайней мере, в конце представления ставлю:
<script type="text/javascript">
$("#listado").on("click", function (e) {
$(".k-grid #idElementColumn").attr('data-val-number', 'Ingrese un número.');
});
</script>
Я делаю это, ставя это на мой взгляд
@Html.DropDownListFor(m => m.BenefNamePos, Model.Options, new { onchange = "changePosition(this);", @class="form-control", data_val_number = "This is my custom message" })