76

假设这个模型:

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我想像服务器端的其他人一样更改错误消息。

4

14 回答 14

79

您可以通过在呈现字段时自己提供data-val-number属性来覆盖消息。这会覆盖默认消息。这至少适用于 MVC 4。

@Html.EditorFor(model => model.MyNumberField, new { data_val_number="提供一个整数,伙计!" })

请记住,您必须在属性名称中使用下划线,Razor 才能接受您的属性。

于 2013-04-18T11:07:50.853 回答
52

你要做的是:

Application_Start()在里面添加以下代码Global.asax

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

在 VS 中右键单击您的 ASP.NET MVC 项目。选择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 中本地化默认错误消息

于 2013-08-22T23:50:34.637 回答
39

这并不容易。默认消息作为嵌入资源存储到System.Web.Mvc程序集中,获取的方法是内部密封内部类 ( System.Web.Mvc.ClientDataTypeModelValidatorProvider+NumericModelValidator.MakeErrorString) 的私有静态方法。就好像微软编码的那个人隐藏了一个最高机密:-)

您可以查看以下描述可能解决方案的博客文章。您基本上需要将现有的ClientDataTypeModelValidatorProvider替换为自定义的。

如果你不喜欢你需要做的硬核编码,你也可以用一个字符串替换你的视图模型中的这个整数值,并在它上面有一个自定义验证属性,它可以进行解析并提供一个自定义错误消息(甚至可以本地化)。

于 2011-01-28T18:27:33.487 回答
23

作为解决此问题的另一种方法,我应用了一个 RegularExpression 属性来捕获无效条目并在那里设置我的消息:

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

这有点小技巧,但这似乎比其他解决方案所呈现的复杂性更可取,至少在我的特定情况下是这样。

编辑:这在 MVC3 中运行良好,但似乎 MVC4+ 可能有更好的解决方案。

于 2011-10-11T17:09:38.730 回答
11

来自我拥有的关于 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 资源文件中提取的。如果您不需要,只需将其替换为您自己的消息即可。

于 2011-06-19T21:47:17.520 回答
7

这是另一种在不更改 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));
于 2011-06-15T14:01:30.920 回答
5

您可以将类设置ResourceKeyClientDataTypeModelValidatorProvider包含FieldMustBeNumeric键的全局资源的名称,以用您的自定义消息替换数字的 MVC 验证错误消息。日期验证错误消息的关键也是FieldMustBeDate.

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

有关如何将文件添加到项目的更多详细信息,请参见此处MyResources.resx

于 2013-02-02T19:32:17.770 回答
3

这是纯 js 中的另一种解决方案,如果您想全局指定消息而不是每个项目的自定义消息,则该解决方案有效。

关键是验证消息是使用每个元素上jquery.validation.unobtrusive.jsdata-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 + ' باید عددی باشد')
});

好消息是它不需要编译,您可以在以后轻松扩展它,虽然不健壮,但速度很快。

于 2014-01-29T12:40:37.183 回答
3

也检查一下:

ASP.NET MVC 3 中的验证完整指南 - 第 2 部分

文章的主要部分如下(复制粘贴)。

创建可在客户端和服务器上运行的功能齐全的自定义验证器有四个不同的部分。首先,我们继承ValidationAttribute并添加我们的服务器端验证逻辑。接下来,我们IClientValidatable在属性上实现以允许将 HTML5data-*属性传递给客户端。第三,我们编写了一个在客户端执行验证的自定义 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 适配器

适配器的工作是读取data-*表单元素上的 HTML5 属性,并将这些数据转换为 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。

于 2015-02-03T10:48:20.677 回答
1

我只是这样做了,然后使用了正则表达式:

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


[RegularExpression(@"^[0-9\.]*$", ErrorMessage = "Invalid Amount")]
public decimal? Amount { get; set; }
于 2012-12-19T12:22:03.807 回答
1

或者您可以简单地执行此操作。

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

希望这可以帮助。

于 2014-07-26T22:27:49.907 回答
1

我把它放在我的视野中

@Html.DropDownListFor(m => m.BenefNamePos, Model.Options, new { onchange = "changePosition(this);", @class="form-control", data_val_number = "This is my custom message" })
于 2018-05-14T14:41:25.857 回答
0

我在 KendoGrid 中遇到了这个问题,我在视图的末尾使用了一个脚本来覆盖 data-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>
于 2014-10-06T15:13:17.060 回答
0

一个简单的方法是,在 ViewModel 上使用数据注释更改消息:

[Required(ErrorMessage ="الزامی")]
[StringLength(maximumLength:50,MinimumLength =2)]
[Display(Name = "نام")]
public string FirstName { get; set; }
于 2020-11-10T22:12:30.500 回答