Communication grille extjs vers WCF ou WebService ASMX "Ajax" via JSON
Je suis actuellement en train d'utiliser le framework extjs.com. Parmi les contrôles de ce framework il existe un contrôle Ext.grid.GridPanel qui, comme son nom l'indique affiche une grille coté client (démo grid extjs).
Pour ceux qui ne connaissent pas extjs, je vous conseille vivement de faire un tour sur la page de démos de ce framework : démos des contrôles extjs, vous risquez d'être étonné.
Comment binder le contrôle grid avec un service WCF ou ASMX "Ajax Enabled" ?
Pour binder un contrôle à une source de donnée, extjs a un mécanisme de "store", celui-ci s'occupe de rechercher les données, les transformer en une donnée utilisable par les contrôles, etc...
Puisqu'un service WCF est capable de nous générer du JSON, le store qui nous intéresse est le JsonStore. Ce "store" permet de faire une requête XMLHttpRequest vers une url nous retournant du JSON. Le JsonStore effectue une requête GET, par défaut WCF n'autorise pas les requêtes GET, il faut donc rajouter l'attribut [WebGet] au niveau du service WCF afin d'autoriser ce verbe.
Voici à quoi ressemble notre service WCF.
[WebGet]
[OperationContract]
public List<Person> GetPersons()
{
return new List<Person>()
{
new Person(){FirstName = "Cyril", LastName = "Durand",
BirthDate = new DateTime(1986, 1, 31), Company = "Freelance"},
new Person(){FirstName = "Toto", LastName="Pouet",
BirthDate = new DateTime(1900, 1, 1), Company="Student"}
};
}
Si vous utilisez un WebService ASMX classique il faut rajouter le paramètre UseHttpGet=true dans l'attribut ScriptMethod.
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public List<Person> GetPersons()
Au niveau du client, il n'y a rien de spécial à configurer, nous n'avons même pas besoin d'utiliser le framework Microsoft Ajax Library ou d'inclure le proxy autogénéré du service WCF (service1.svc/js).
Voici le code nécessaire.
var store = new Ext.data.JsonStore({
url : 'service.svc/GetPersons',
root : 'd', // anti CSRF attack
fields: [
'FirstName',
'LastName',
'Company',
{name:'BirthDate', type:'date', dateFormat: 'atlas'}
]
});
var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{header: "Prenom", width: 75, sortable: true, dataIndex: 'FirstName'},
{header: "Nom", width: 75, sortable: true, dataIndex: 'LastName'},
{header: "Date de naissance", width: 155, sortable: true,
dataIndex: 'BirthDate', renderer: Ext.util.Format.dateRenderer('m/d/Y')},
{id:'company',header: "Nom de la companie", width: 100,
sortable: true, dataIndex: 'Company'}
],
loadMask : true,
autoExpandColumn: 'company',
height:350,
width:800
});
grid.render(document.body);
store.load();
Si vous voulez renvoyer des données de type DateTime voici une petite astuce permettant de déserializer une Date "WCF" avec extjs.
// petite bidouille pour deserialiser les dates atlas avec extjs
Date.parseFunctions['atlas'] = '_parseAtlas';
Date._parseAtlas = function(input){
input = input.replace(
new RegExp('/Date\\((-?[0-9]+)(?:[a-zA-Z]|(?:\\+|-)[0-9]{4})?\\)/', 'g'),
'(new Date($1))');
return eval(input);
}
Cette astuce est à exécuter qu'une seule fois au lancement de votre application.