Mittendrin.

Zurück

Flurfunk der eXperts.

Hier erfahren Sie mehr über eXperts, Technologien und das wahre Leben in der SDX.

ASP.NET MVC I18n – Teil 8: Datenvalidierung

20.02.201408:00 Uhr , Alexander Jung

Der letzte Beitrag hat gezeigt, wie man Datenbezeichner und Validierungsfehler lokalisieren kann. Es wird Zeit, sich der Validierung selbst zu widmen.

Hinweis: Dieser Beitrag ist Teil einer Serie, die Übersicht findet sich hier.

 

 

Datenvalidierung ist ein weiterer Aspekt zum Thema Internationalisierung, der in weiten Teilen gut dokumentiert ist, aber eben oft nicht vollständig.

Kommen wir kurz zur letzten Fehlermeldung aus dem letzten Beitrag zurück:

Lokalisierung-7-app4

Die Fehlermeldung beim Datum in Deutsch statt Englisch zu bekommen hilft nicht wirklich über die Tatsache hinweg, dass hier gar kein Fehler vorliegt.

Das Grundproblem ist, dass die von ASP.NET MVC eingesetzte jQuery Validation normale JavaScript-Methoden zur Validierung verwendet. Diese kommen natürlich nur mit amerikanischem Format zurecht und produzieren daher u.U. falsche Fehlermeldungen. Schlimmer noch sind Fälle, in denen keine Validierungsfehler entstehen, weil die falschen Werte validiert werden. Punkt und Komma haben bei Zahlen vertauschte Bedeutung, wenn man zwischen deutschem und amerikanischem Format wechselt, gleiches gilt für Position von Tag und Monat zwischen amerikanischem und französischem Datumsformat.

Die typische Antwort auf dieses Problem ist, sich jQuery Globalize von github zu besorgen und zu verwenden… was etwas Handarbeit erfordert.

 

Zuerst…

braucht man globalize.js (auf github unter lib), dazu die notwendigen Lokalisierungsdateien (zu finden unter libcultures). Wer eine komprimierte Version der Script-Datei haben möchte (globalize.min.js im Bild unten), muss sich diese bereits selbst bauen, etwa über http://jscompress.com/. All Dateien packt man dann in den /Scripts Ordner im Web-Projekt:

Lokalisierung-8-files

Hinweis: Es gibt ebenfalls mittlerweile ein nuget package, das die Dateien ohne Umweg über github bereitstellt – einschließlich aller verfügbaren Lokalisierungsdateien – aber immer noch ohne komprimierte Variante.

 

Zweitens…

… müssen die Skripte in unsere Views aufgenommen werden. Das geht in zwei Varianten, die man beide als Beispiele im Web findet:

A) Man definiert ein entsprechendes bundle…

   1: bundles.Add(new ScriptBundle("~/bundles/globalization") 

   2:     .Include("~/Scripts/globalize.js") 

   3:     .Include("~/Scripts/globalize.culture.*") 

   4:     .Include("~/Scripts/globalize.initialize.js") 

   5: ); 

… und nimmt das _layout.cshtml auf bevor die „script“ section gerendert wird, denn dort kommt später die Validierung ins Spiel:

   1: @Scripts.Render("~/bundles/globalization") 

   2: @RenderSection("scripts", required: false) 

B) Anstatt alle Lokalisierungsdateien aufzunehmen reicht es auch, sich auf die aktuell gerade benötigte zu beschränken. Das geht einfacher ohne extra ein bundle zu definieren:

   1: @Scripts.Render("~/Scripts/globalize.js") 

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

   3: @Scripts.Render("~/Scripts/globalize.initialize.js") 

 

Drittens…

… müssen wird die Sprache auf der Clientseite initialisieren.

Dafür ist ein Aufruf der Funktion Globalize.culture(…) mit der entsprechenden Angabe notwendig. Man könnte diesen Aufruf dynamisch per Code erzeugen – was sehr oft so empfohlen wird. Andererseits ist diese Information ja schon auf dem Client verfügbar (wir haben sie schließlich selbst bereitgestellt). Eine statische Script-Datei globalize.initialize.js sollte also ausreichen, und frisst zudem weniger Ressourcen:

   1: $(document).ready(function () { 

   2:     // use the language provided from server... 

   3:     var lang = $("html").attr("lang");  

   4:     if (typeof Globalize != 'undefined') 

   5:         Globalize.culture(lang); 

   6: }); 

 

Viertens…

…fehlt uns noch der Verbindung.

Wir haben die notwendigen Funktionen für lokalisierte Datenformate, aber jQuery Validation nutzt diese noch nicht. Der letzte Schritt ist also, diese Verbindung herzustellen. Was immer passieren muss… . Was jemand Microsoft hätte bereitstellen können… . Oder wenigstens vollständig hätte erklären können… .

Stattdessen findet man nur die halbgare Darstellung im Tutorial. [UPDATE: Wie sich herausstellte bin ich nicht der Erste dem das auffällt. Mehr dazu am Ende.]

jQuery hat ein Objekt, das die notwendigen Validierungsmethoden verwaltet: $.validator.methods. Diese müssen durch Varianten ersetzt werden, die die von Globalize bereitgestellten Methoden verwenden. Für MVC und unobtrusive validation geht es dabei um die 5 Methoden number, date, min, max und range. Hier die entsprechende Script-Datei globalize.validation.js:

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

   2:  

   3: $.validator.methods.number = function (value, element) { 

   4:     return this.optional(element) || !isNaN(Globalize.parseFloat(value)); 

   5: } 

   6:  

   7: $.validator.methods.date = function (value, element) { 

   8:     if (this.optional(element)) 

   9:         return true; 

  10:     var result = Globalize.parseDate(value); 

  11:     return !isNaN(result) && (result != null); 

  12: } 

  13:  

  14: $.validator.methods.min = function( value, element, param ) { 

  15:     return this.optional(element) || Globalize.parseFloat(value) >= param; 

  16: } 

  17:  

  18: $.validator.methods.max = function( value, element, param ) { 

  19:     return this.optional(element) || Globalize.parseFloat(value) <= param; 

  20: } 

  21:  

  22: $.validator.methods.range = function (value, element, param) { 

  23:     if (this.optional(element)) 

  24:         return true; 

  25:     var result = Globalize.parseFloat(value); 

  26:     return (result >= param[0] && result <= param[1]); 

  27: } 

Hinweis: Wer jQuery validation direkt verwendet (d.h im JavaScript und nicht via unobtrusive validation), der muss natürlich alle Methoden in $.validator.methods entsprechend ersetzten.

Diese Script-Datei kann man einfach in das existierende bundle für Validierungen mit aufnehmen:

   1: var bundle = bundles.GetBundleFor("~/bundles/jqueryval"); 

   2: bundle.Include("~/Scripts/globalize.validation.js"); 

 

Und jetzt funktioniert unsere Validierung so wie sie soll, und berücksichtigt deutsche Datums- und Zahlenformate korrekt.

 

UPDATE: Gerade als ich diesen Beitrag fertig hatte bin ich über John‘s Beitrag gestolpert. Das ist der erste Beitrag den ich gefunden habe, der Globalize und jQuery validation sowohl korrekt, als auch vollständig verknüpft. Außerdem stellt er ein nuget package bereit, so dass man sich einige Arbeit – nicht alles – sparen kann.

2 Kommentare

08.06.201612:43 Uhr
Horst

Top Anleitung!

Leider von 2014 und daher nicht mehr ganz aktuell.

Aber das Problem besteht nach wie vor. Keine brauchbare Anleitung, wie man jetzt mit Globalize 1.1.1 verfahren muss, damit es läuft.

Wäre daher super, wenn ihr diese Anleitung mal aktualisiert!

LG Horst

15.06.201610:54 Uhr
Alexander

Danke für das Feedback.

Der Hinweis bzgl. der Aktualität ist schon richtig, allerdings bin ich zur Zeit verstärkt Xamarin/Mobile-Projekten unterwegs, so dass ich nicht weiß, ob/wann ich dazu komme. Es liegt leider in der Natur der Sache, dass (speziell technische) Blogbeiträge veralten.

Vielleicht helfen folgende Links weiter:

John (letzter Link) stellt seinen Code als Nuget-package und via github zur Verfügung.

HIH,
Alexander

Dein Kommentar wartet auf Freischaltung.

Artikel kommentieren

Zurück

Tag Cloud