ASP.NET MVC – Ajax et CultureInfo

Je regarde en ce moment le framework MVC de l’équipe ASP.NET. Premier gros développement web avec code source ouvert, on en est à la 5ème preview de ce qui sera sans doute un élèment d’ASP.NET Extensions.

J’aborderai dans un autre billet mon expérience avec le framework, aujourd’hui je voulais parler de l’intégration d’Ajax. Il est possible d’utiliser le helper Ajax.Form pour soumettre une requête au serveur.

Exemple dans un grid (voir le projet MVC Contrib) j’ai un bouton “EDIT” qui me permet de charger toutes les informations d’une entité pour édition (alors que dans le grid les entités sont “lazy-loadées”, ici l’adresse n’est pas chargée). Ceci étant possible sur la même page, j’aimerai pouvoir accèder au détail sans recharger toute la page d’où l’intérêt d’un formulaire “ajax”.

Voici une capture d’écran de ce “master-détails” :

master détails, cliquer pour zoomer

Voici le code du grid comportant la colonne du bouton :

column.For(“Edit”).Do(p => {%> <%using (Ajax.Form(“Edit”, “Subscriber”, new AjaxOptions { OnSuccess = “onEditResult”, HttpMethod = “GET” })) {%> <%=Html.Hidden(“idSub”, p.Id.ToString())%> <% } %><% }); } ); %>

La méthode du controller appellée (“EDIT”) va renvoyer du JSON :

[AcceptVerbs(“GET”)] public JsonResult Edit(string idSub) { Subscriber sub = _service.GetSubscriberWithAddress(new Guid(idSub)); return Json(sub); }

Côté client la librairie Microsoft Ajax (qui peut être utilisée sans ASP.NET) apporte des fonctionnalités comme la désérialisation JSON, le formattage de date selon la langue courante, ou “tout simplement” l’inspection du DOM :

function onEditResult(ajaxContext) { var sub = Sys.Serialization. JavaScriptSerializer.deserialize( ajaxContext.get_response().get_responseData(), false); $get(‘IdSubEdit’).value = sub.Id; $get(‘Dob’).value = String.localeFormat("{0:d}", sub.Dob); $get(‘FirstName’).value = sub.FirstName; (…) }

Ici l’entitée sert à remplir les champs du formulaire. Un petit problème subsiste : la méthode String.localeFormat dépend de l’objet global  “Sys.CultureInfo.CurrentCulture”. Or comme nous sommes en mode “MVC” et non “WebForms” on peut pas utiliser le contrôle ScriptManager qui permet à partir de la langue du navigateur de générer les scripts pour la culture courante. La culture est celle par défaut i.e. US.

Toutefois en regardant le code source de la librairie on s’aperçoit que la culture par défaut est parsée à partir du chaîne de caractère en JSON.

Sys.CultureInfo.CurrentCulture = Sys.CultureInfo._parse(__cultureInfo); //cultureInfo est de style var __cultureInfo = ‘{“name”:“en-US”,“numberFormat”:{

et la méthode parse :

Sys.CultureInfo.\_parse = function Sys$CultureInfo$\_parse(value) {
var cultureInfo = Sys.Serialization.JavaScriptSerializer.deserialize(value);
return new Sys.CultureInfo(cultureInfo.name,cultureInfo.numberFormat, cultureInfo.dateTimeFormat);

}

Pour re-initialiser correctement on peut ajouter dans la page aspx un script qui prend la culture et crée la chaîne JSON correspondante :

JavaScriptSerializer jss = new JavaScriptSerializer(); CultureInfo culte = System.Threading.Thread.CurrentThread.CurrentUICulture;

var cultJS = new CultureInfoJS() { dateTimeFormat = culte .DateTimeFormat, name = culte .CurrentUICulture.Name, numberFormat = culte .NumberFormat }; this.CultureInfoSerialized = jss.Serialize(cultJS);

(la classe CultureInfoJS est juste un “place holder” avec les trois attributs pour construire un argument attendu par la méthode parse)

Voici le code généré (un peu verbeux mais les attributs de globalization sont nombreux) :

code généré

Ici je prends la culture du serveur car je dois l’utiliser pour un parsing mais rien n’empêche de prendre la langue du navigateur comme expliqué sur le site de MSDN pour  ASP.NET.

CultureInfo culte = CultureInfo.CreateSpecificCulture(Request.UserLanguages[0]); au lieu de System.Threading.Thread.CurrentThread.CurrentUICulture

PS : attention si vous faites l’update ASP.NET MVC Preview 4 à 5 il faut mettre à jour les deux scripts JS du template de prokjet VIsual Studio qui sont générés dans le répertoire “Content”.

billet publié dans les rubriques coding le