ASP.NET MVC Localize Numeric (data-val-number) Validation

Another buggy experience in ASP.NET MVC. This has to do with validation, more specifically numeric validation. Whenever you have a numeric property on your view models, ASP.NET MVC automatically adds some implicit validation to ensure that whatever entered in fact is a numeric value.

Might be good in most cases, but here’s the problem. The validation mechanism writes the error messages in english. So for any app that targets a non-english audience, this needs to be changes.

But that’s easier said than done. The code in ASP.NET MVC that generates the error message for the implicit numeric validator, looks like this:

private static string MakeErrorString(string displayName) { // use CurrentCulture since this message is intended for the site visitor return String.Format(CultureInfo.CurrentCulture, MvcResources.ClientDataTypeModelValidatorProvider_FieldMustBeNumeric, displayName); }

To make matter worse, this is a method from an internal, sealed class. They didn’t want you to change this.

The only option is to remove the validator, and get rid of the implicit validation. To be honest, I prefer to take care of validation myself, through data annotations on my view models. I don’t like when too much gets done implicitly. I want to be in control, and I want to know what is going on.

You can remove the validator in Global.asax:

foreach (ModelValidatorProvider prov in ModelValidatorProviders.Providers) { if (prov.GetType().Equals(typeof(ClientDataTypeModelValidatorProvider))) { ModelValidatorProviders.Providers.Remove(prov); break; } }

If you’d like to keep the numeric validation, but be able to override the error message, there’s a great way to roll your own ClientDataTypeModelValidatorProvider that does this the right way.

Things will get better

I was browsing through the source code of ASP.NET MVC 4, and found a changeset that looks like will fix this issue. In short, it will be possible to define your own ResourceClassKey, and the MVC framework will use that before using default error messages. Nice!