AJ's blog

January 25, 2014

ASP.NET MVC I18n – Part 8: Data Validation

Filed under: .NET, .NET Framework, ASP.NET MVC, HTML5, Internationalization — ajdotnet @ 3:13 pm

The last post showed how to display localized validation error messages. Time to be able to actually validate😉

Note: This post is part of a series

This is another topic that is widely documented for the most part, but has some notable gaps.

Remember the error from last post:

Having the error message in localized German does not solve the fact that the date is actually in the valid local format in the first place. We should not even get an error.

The basic problem is that jQuery validation uses regular JavaScript methods to do validation, thus some valid data, if in localized format, will produce validation errors. But even worse is the fact that some data validates just fine – but with a wrong value. E.g. point and comma in numeric values switch their meaning from en-US to de-DE, similarly day and month change their position between en-US and fr-FR.

The generally cited answer to solve this issue is to use Globalize from github… which requires a little handiwork.

 

First…

… you need to grab the globalize.js file from github under lib\ as well as the necessary localizations under lib\cultures\. If you require compressed versions (globalize.min.js below), you’ll have to create them yourself, e.g using http://jscompress.com/, as they are not provided. All files are then placed in the /Scripts folder of your web project.

Note: there is also a nuget package, which will install these files – including all localizations, but still no minified version.

 

Second…

… the scripts need to be included in our views. There are two options, which can both be found:

A) Define a respective bundle…

bundles.Add(new ScriptBundle("~/bundles/globalization")
    .Include("~/Scripts/globalize.js")
    .Include("~/Scripts/globalize.culture.*")
    .Include("~/Scripts/globalize.initialize.js")
);

and render it in _layout.cshtml – before the „script“ section is rendered, because that is where validation will come into play:

@Scripts.Render("~/bundles/globalization")
@RenderSection("scripts", required: false)

B) Instead of including all localization files (i.e. the globalize.culture.*.js files) you could also just include the necessary one. In that case it’s probably simpler to go without bundle:

@Scripts.Render("~/Scripts/globalize.js")
@Scripts.Render("~/Scripts/globalize.culture." + Culture + ".js")
@Scripts.Render("~/Scripts/globalize.initialize.js")

 

Third…

… we need to initialize the culture on the client side.

For this a call to Globalize.culture is necessary. You could generate the respective call an the server, passing in the current UI culture – which is what you’ll see very often in tutorials. However the information is already available on the client (because we put it there), thus a static script globalize.initialize.js will do (and will benefit http caching):

$(document).ready(function () {
    // use the language provided from server…
    var lang = $("html").attr("lang"); 
    if (typeof Globalize != ‘undefined’)
        Globalize.culture(lang);
});

 

Fourth…

…we need some plumbing.

We have the necessary infrastructure for localization, but jQuery validation does not use it yet. The final step is to wire jQuere validation with the new globalize methods. This is something that everyone has to do. Something that is quite simple. Something that could have been provided. Something that someone could have told you how to do. Guess what? Nobody did. [UPDATE: Turns out, I was wrong, see below. I still kept the following content for the explanations.]

jQuery has an object that provides the necessary validation methods: $.validator.methods. All that is necessary is to reroute them to replacements that make use of the globalization library. For MVC and unobtrusive validation, that requires just 5 methods: number, date, min, max, and range. In yet another additional script file globalize.validation.js:

// replace methods in jquery.validate.js ($.validator.methods) as necessary for localized validation:

$.validator.methods.number = function (value, element) {
    return this.optional(element) || !isNaN(Globalize.parseFloat(value));
}

$.validator.methods.date = function (value, element) {
    if (this.optional(element))
        return true;
    var result = Globalize.parseDate(value);
    return !isNaN(result) && (result != null);
}

$.validator.methods.min = function( value, element, param ) {
    return this.optional(element) || Globalize.parseFloat(value) >= param;
}

$.validator.methods.max = function( value, element, param ) {
    return this.optional(element) || Globalize.parseFloat(value) <= param;
}

$.validator.methods.range = function (value, element, param) {
    if (this.optional(element))
        return true;
    var result = Globalize.parseFloat(value);
    return (result >= param[0] && result <= param[1]);
}

Note: If you are using jQuery validation directly (not via unobtrusive validation), you’ll need to wire all methods in $.validator.methods respectively.

What‘s left is including this script in a bundle. Since there is already a bundle associated with validation and included in respective edit views, I just extended it:

var bundle = bundles.GetBundleFor("~/bundles/jqueryval");
bundle.Include("~/Scripts/globalize.validation.js");

 

And now our validation code works just fine, properly recognizing German date and number formats.

UPDATE: Just when I finished writing this post, I stumbled upon John‘s post, which is the first one I found that connects Globalize and jQuery validation both correctly and completely, and even provides a nuget package.

 

That’s all for now folks,
AJ.NET

4 Comments »

  1. Hi, I’ve been looking for ‘globalize.js’ file in https://github.com/jquery/globalize, but I can’t find it.

    Please help me.

    Comment by Oscar Polanco — March 25, 2014 @ 7:26 am

  2. They’re working on a new implementation: “We’re working on the migration to using the Unicode CLDR. This is an alpha version of Globalize: 1.0.0-pre.”
    But you can find the “old” implementation under “Releases”, e.g. https://github.com/jquery/globalize/releases/tag/v0.1.1
    Or use the Nuget Package http://www.nuget.org/packages/jquery-globalize

    Comment by ajdotnet — March 26, 2014 @ 10:04 am

  3. Hi,
    It seems they do have updated the Globalize.js plugin. Do you know of any complete walk through like this article (which is great b.t.w.)?

    Comment by Ruud — May 29, 2015 @ 10:02 am

  4. Thanks for the update and the feedback.
    No I don’t know about any walkthroughs. But if it has been updated the people involved may have written about it somewhere…?

    Comment by ajdotnet — May 29, 2015 @ 5:28 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: