如何在@Html帮助程序生成的MVC中更改"data-val-number"消息验证

GtE*_*tEx 75 validation asp.net-mvc localization unobtrusive-validation asp.net-mvc-3

假设这个模型:

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

和观点:

@Html.TextBoxFor(Function(m) m.PercentChange)
Run Code Online (Sandbox Code Playgroud)

将继续这个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" />
Run Code Online (Sandbox Code Playgroud)

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

小智 73

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

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

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

  • 我看不出这是怎么回事.如果这是一个新的`htmlAttributes`对象,它可能会工作,但它是一个`additionalViewData`对象,所以你只需要一个名为`data_val_number`的额外属性. (4认同)
  • @HenningJ对我很有用,谢谢你给我节省了很多时间:) (3认同)
  • 我同意@Sprintstar。它对我不起作用,但`@Html.EditorFor(model =&gt; model.age, new { htmlAttributes = new { @class = "form-control", data_val_required = "Field required"} })` 做了。 (3认同)

Len*_*rri 50

你要做的是:

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

 ClientDataTypeModelValidatorProvider.ResourceClassKey = "Messages";
 DefaultModelBinder.ResourceClassKey = "Messages";
Run Code Online (Sandbox Code Playgroud)

在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.
Run Code Online (Sandbox Code Playgroud)

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

你完成了.


查看此帖子了解更多详情:

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

  • 这真的是这个问题的最佳答案. (5认同)
  • 虽然@DarinDimitrov有一个有效的解决方案,但对我而言,这应该是公认的答案,因为它使用内置的可扩展机制,而不是复制整个.Net类并更改它,这样可维护性更低 (4认同)
  • @Nick Coad.是的,这是最好的 - 而且这个问题没有多余的答案.我可以确认它适用于MVC 4和MVC 5 (2认同)

Dar*_*rov 38

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

您可以查看以下博客文章,其中介绍了可能的解决方案.您基本上需要使用自定义ClientDataTypeModelValidatorProvider替换现有的ClientDataTypeModelValidatorProvider.

如果您不喜欢需要执行的硬核编码,您还可以使用字符串替换视图模型中的此整数值,并在其上具有自定义验证属性,该属性将执行解析并提供自定义错误消息(甚至可以本地化).

  • 查看MVC 4的源代码,看起来它正在被修复,允许我们指定自己的`ResourceClassKey` http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/06f52b894414#src%2fSystem.Web.Mvc% 2fClientDataTypeModelValidatorProvider.cs (8认同)
  • 哇,你一定很擅长这些秘密的东西:).非常强硬的代码.我不明白为什么他们这么难!我有点喜欢他们在MVC3 RTM中修复这些东西,但他们没有.我把它放在我的控制器中只是为了检查它是否正常工作.并且感谢它就像一个魅力.但我应该把这个'删除'的东西放在哪里?在我的`global.asax`中?那好吗? (3认同)
  • 是.在这种情况下,替换ResourceClassKey并使用名称FieldMustBeNumeric.对于必需和无效的错误混淆使用另一种方法也由Darin Dimitrov提出http://stackoverflow.com/questions/12545176/mvc-4-ignores-defaultmodelbinder-resourceclasskey/12545997#12545997 (3认同)
  • @GtEx,是的`Providers.Remove`和`Providers.Add`应该放在Global.asax的`Application_Start`方法中. (2认同)

Mat*_*ols 23

作为替代方法,我应用RegularExpression属性来捕获无效条目并在那里设置我的消息:

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

这有点像黑客,但这似乎比其他解决方案所呈现的复杂性更好,至少在我的特定情况下.

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

  • 没有任何争论,这是一个黑客攻击.我唯一的辩护是,它应该非常容易覆盖框架中的任何错误消息. (2认同)

Den*_*eev 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()); 
} 
Run Code Online (Sandbox Code Playgroud)

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


Phi*_*ale 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));
Run Code Online (Sandbox Code Playgroud)


小智 5

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

ClientDataTypeModelValidatorProvider.ResourceKey="MyResources"; // MyResource is my global resource
Run Code Online (Sandbox Code Playgroud)

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