asp.net-mvc MVC 中的“data-val-number”消息验证由@Html helper 生成时如何更改

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4828297/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:48:49  来源:igfitidea点击:

How to change 'data-val-number' message validation in MVC while it is generated by @Html helper

asp.net-mvcasp.net-mvc-3localizationunobtrusive-validationvalidation

提问by GtEx

Assume this model:

假设这个模型:

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

and the view:

和观点:

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

will proceed this html:

将继续这个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" />

I want to customize the data-val-numbererror message which I guess has generated because PercentChangeis an Integer. I was looking for such an attribute to change it, rangeor whatever related does not work.
I know there is a chance in editing unobtrusive's js file itself or override it in client side. I want to change data-val-number's error message just like others in server side.

我想自定义data-val-number我猜已经生成的错误消息,因为它PercentChange是一个Integer. 我正在寻找这样一个属性来改变它,range或者任何相关的都不起作用。
我知道有机会编辑不显眼的 js 文件本身或在客户端覆盖它。我想像data-val-number服务器端的其他人一样更改的错误消息。

采纳答案by Darin Dimitrov

This is not gonna be easy. The default message is stored as an embedded resource into the System.Web.Mvcassembly and the method that is fetching is a private static method of an internal sealed inner class (System.Web.Mvc.ClientDataTypeModelValidatorProvider+NumericModelValidator.MakeErrorString). It's as if the guy at Microsoft coding this was hiding a top secret :-)

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

You may take a look at the following blog postwhich describes a possible solution. You basically need to replace the existing ClientDataTypeModelValidatorProviderwith a custom one.

您可以查看以下博客文章,其中描述了一种可能的解决方案。您基本上需要用自定义的替换现有的ClientDataTypeModelValidatorProvider

If you don't like the hardcore coding that you will need to do you could also replace this integer value inside your view model with a string and have a custom validation attribute on it which would do the parsing and provide a custom error message (which could even be localized).

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

回答by HenningJ

You can override the message by supplying the data-val-numberattribute yourself when rendering the field. This overrides the default message. This works at least with MVC 4.

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

@Html.EditorFor(model => model.MyNumberField, new { data_val_number="Supply an integer, dude!" })

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

Remember that you have to use underscore in the attribute name for Razor to accept your attribute.

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

回答by Leniel Maccaferri

What you have to do is:

你需要做的是:

Add the following code inside Application_Start()in Global.asax:

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

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

Right click your ASP.NET MVC project in VS. Select Add => Add ASP.NET Folder => App_GlobalResources.

在 VS 中右键单击您的 ASP.NET MVC 项目。选择Add => Add ASP.NET Folder => App_GlobalResources

Add a .resxfile called Messages.resxin that folder.

添加在该文件夹中.resx调用Messages.resx的文件。

Add these string resources in the .resxfile:

.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.

Change the FieldMustBeNumericvalue as you want... :)

FieldMustBeNumeric根据需要更改值... :)

You're done.

你完成了。



Check this post for more details:

查看此帖子以获取更多详细信息:

Localizing Default Error Messages in ASP.NET MVC and WebForms

本地化 ASP.NET MVC 和 WebForms 中的默认错误消息

回答by Matthew Nichols

As an alternate way around this, I applied a RegularExpression attribute to catch the invalid entry and set my message there:

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

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

This slightly a hack but this seemed preferable to the complexity the other solutions presented, at least in my particular situation.

这有点黑客,但这似乎比其他解决方案提出的复杂性更可取,至少在我的特定情况下。

EDIT: This worked well in MVC3 but it seems that there may well be better solutions for MVC4+.

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

回答by Denis Valeev

From this book on MVC 3 that I have. All you have to do is this:

来自我所拥有的关于 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()); 
} 

Notice how the ErrorMessage is yielded, you specify the current culture and the localized message is extracted from the ValidationMessages(here be culture specifics).resx resource file. If you don't need that, just replace it with your own message.

请注意 ErrorMessage 是如何产生的,您指定当前区域性并从 ValidationMessages(这里是区域性细节).resx 资源文件中提取本地化消息。如果您不需要它,只需将其替换为您自己的消息即可。

回答by Phil Hale

Here is another solution which changes the message client side without changed MVC3 source. Full details in this blog post:

这是另一个解决方案,它在不更改 MVC3 源的情况下更改消息客户端。此博客文章中的完整详细信息:

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

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

In short what you need to do is include the following script after jQuery validation is loaded plus the appropriate localisation file.

简而言之,您需要做的是在加载 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));

回答by reza taroosheh

You can set ResourceKey of ClientDataTypeModelValidatorProvider class to name of a global resource that contains FieldMustBeNumeric key to replace mvc validation error message of number with your custom message. Also key of date validation error message is FieldMustBeDate.

您可以将 ClientDataTypeModelValidatorProvider 类的 ResourceKey 设置为包含 FieldMustBeNumeric 键的全局资源的名称,以用您的自定义消息替换数字的 mvc 验证错误消息。日期验证错误消息的另一个关键是 FieldMustBeDate。

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

回答by mohas

Here is another solution in pure js that works if you want to specify messages globally not custom messages for each item.

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

The key is that validation messages are set using jquery.validation.unobtrusive.jsusing the data-val-xxxattribute on each element, so all you have to do is to replace those messages before the library uses them, it is a bit dirty but I just wanted to get the work done and fast, so here it goes for number type validation:

关键是验证消息是使用每个元素上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 + ' ???? ???? ????')
});

the good thing is that it does not require compiling and you can extend it easily later, not robust though, but fast.

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

回答by Kamran

Check this out too:

也看看这个:

The Complete Guide To Validation In ASP.NET MVC 3 - Part 2

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

Main parts of the article follow (copy-pasted).

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

There are four distinct parts to creating a fully functional custom validator that works on both the client and the server. First we subclass ValidationAttributeand add our server side validation logic. Next we implement IClientValidatableon our attribute to allow HTML5 data-*attributes to be passed to the client. Thirdly, we write a custom JavaScript function that performs validation on the client. Finally, we create an adapter to transform the HTML5 attributes into a format that our custom function can understand. Whilst this sounds like a lot of work, once you get started you will find it relatively straightforward.

创建一个可在客户端和服务器上运行的全功能自定义验证器有四个不同的部分。首先,我们子类化ValidationAttribute并添加我们的服务器端验证逻辑。接下来我们实现IClientValidatable我们的属性,以允许将 HTML5data-*属性传递给客户端。第三,我们编写了一个在客户端执行验证的自定义 JavaScript 函数。最后,我们创建了一个适配器,将 HTML5 属性转换为我们的自定义函数可以理解的格式。虽然这听起来像很多工作,但一旦开始,您会发现它相对简单。

Subclassing ValidationAttribute

子类化 ValidationAttribute

In this example, we are going to write a NotEqualTo validator that simply checks that the value of one property does not equal the value of another.

在这个例子中,我们将编写一个 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;
    }        
}

Add the new attribute to the password property of the RegisterModel and run the application.

将新属性添加到 RegisterModel 的密码属性并运行应用程序。

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

Implementing IClientValidatable

实现 IClientValidatable

ASP.NET MVC 2 had a mechanism for adding client side validation but it was not very pretty. Thankfully in MVC 3, things have improved and the process is now fairly trivial and thankfully does notinvolve changing the Global.asaxas in the previous version.

ASP.NET MVC 2 有一种添加客户端验证的机制,但它不是很漂亮。幸运的是,在 MVC 3 中,情况有所改善,现在该过程相当简单,幸运的是,它不像Global.asax以前的版本那样涉及更改。

The first step is for your custom validation attribute to implement IClientValidatable. This is a simple, one method interface:

第一步是让您的自定义验证属性实现 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 };
}

If you run the application now and view source, you will see that the password input html now contains your notequaltodata attributes:

如果您现在运行应用程序并查看源代码,您将看到密码输入 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>

Creating a custom jQuery validate function

创建自定义 jQuery 验证函数

All of this code is best to be placed in a separate JavaScript file.

所有这些代码最好放在一个单独的 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));

Depending on your validation requirements, you may find that the jquery.validate library already has the code that you need for the validation itself. There are lots of validators in jquery.validate that have not been implemented or mapped to data annotations, so if these fulfil your need, then all you need to write in javascript is an adapter or even a call to a built-in adapter which can be as little as a single line. Take a look inside jquery.validate.jsto find out what is available.

根据您的验证要求,您可能会发现 jquery.validate 库已经包含验证本身所需的代码。jquery.validate 中有很多验证器还没有实现或映射到数据注释,所以如果这些满足你的需要,那么你只需要在 javascript 中编写一个适配器,甚至调用一个内置的适配器,它可以只需一行。查看jquery.validate.js以找出可用的内容。

Using an existing jquery.validate.unobtrusive adapter

使用现有的 jquery.validate.unobtrusive 适配器

The job of the adapter is to read the HTML5 data-*attributes on your form element and convert this data into a form that can be understood by jquery.validate and your custom validation function. You are not required to do all the work yourself though and in many cases, you can call a built-in adapter. jquery.validate.unobtrusive declares three built-in adapters which can be used in the majority of situations. These are:

适配器的工作是读取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.

If your validator does not fit into one of these categories, you are required to write your own adapter using the jQuery.validator.unobtrusive.adapters.addmethod. This is not as difficulty as it sounds and we'll see an example later in the article.

如果您的验证器不属于这些类别之一,您需要使用该jQuery.validator.unobtrusive.adapters.add方法编写自己的适配器。这并不像听起来那么困难,我们将在本文后面看到一个示例。

We use the addSingleValmethod, passing in the name of the adapter and the name of the single value that we want to pass. Should the name of the validation function differ from the adapter, you can pass in a third parameter (ruleName):

我们使用该addSingleVal方法,传入适配器的名称和我们要传递的单个值的名称。如果验证函数的名称与适配器不同,您可以传入第三个参数 ( ruleName):

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

At this point, our custom validator is complete.

至此,我们的自定义验证器就完成了。

For better understanding refer to the article itselfwhich presents more description and a more complex example.

为了更好地理解,请参阅文章本身,其中提供了更多描述和更复杂的示例。

HTH.

哈。

回答by Edward Disi

Or you can simply do this.

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

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

Hope this helps.

希望这可以帮助。