Async data con jQuery, Flexigrid e Asp.Net MVC
Dopo aver introdotto jQuery e Flexigrid nel nostro progetto Asp.Net MVC implementiamo una fonte dati asincrona per la nostra griglia.
Prima di tutto definiamo dei dati di esempio su cui lavorare estendendo la classe SampleData aggiungendo un metodo per ottenere un set di dati su cui lavorare.
Aggiungiamo la proprietà LotOfContacts che genera un set di dati e li memorizza in un datamember statico per mantenere costante il set di dati tra le richieste.
1: public static class SampleData
2: { 3: static IQueryable<ContactModel> _cache = null;
4:
5: public static IQueryable<ContactModel> LotOfContacts
6: { 7: get
8: { 9: return _cache ?? (_cache = GenerateRandomContacts(100));
10: }
11: }
12:
13: private static IQueryable<ContactModel> GenerateRandomContacts(int amount)
14: { 15: ...
16: }
17:
18: }
La generazione pseudo-random dei dati avviene con il seguente algorimo
1: private static IQueryable<ContactModel> GenerateRandomContacts(int amount)
2: { 3: string[] names = { "Andrea", "Stefano", "Roberto", "Alessandro", "Gian Maria", "Diego" }; 4: string[] surnames = { "Rossi", "Verdi", "Bianchi", "Conti", "Russo", "Ferrari", "Esposito" }; 5: string[] addresses = { "Via Garibaldi", "Via Verdi", "Via Bianchi", "Piazza Libertà", "Largo stretto", "Corso Magenta", "Via Litoranea" }; 6: string[] phones = { "555-1111", "555-2222", "555-3333", "555-4444", "555-5555", "555-6666", "555-7777" }; 7: Random r = new Random(amount);
8:
9: IList<ContactModel> list = new List<ContactModel>();
10: for (int c = 1; c <= amount; c++)
11: { 12: list.Add(new ContactModel(c.ToString())
13: { 14: Name =
15: string.Format("{0} {1}", names[r.Next(names.Length)], 16: surnames[r.Next(surnames.Length)]),
17: Address = string.Format("{0} {1}", addresses[r.Next(addresses.Length)], c), 18: Phone = phones[r.Next(phones.Length)]
19: }
20: );
21: }
22:
23: return list.AsQueryable();
24: }
La scelta di ritornare un IQueryable<T> è dettata dalla necessità di poter interrogare tramite Linq la nostra "base dati". La classe ContactModel è stata modificata con l'aggiunta di un ID utile per identificare il record nella selezione in griglia.
Modifichiamo ora Tutorial3.aspx per indicare la fonte dati e configurare la griglia
1: <script type="text/javascript">
2: $(function() { 3: <%= Html.NewFlexiGrid("Contacts") 4: .AddColumn("Name", "Name", 200, true, FlexiGridBuilder.Align.left) 5: .AddColumn("Address", "Address", 180, true, FlexiGridBuilder.Align.left) 6: .AddColumn("Phone", "Phone", 120, true, FlexiGridBuilder.Align.left) 7: .AddSearchItem("Name", "Name", true) 8: .AddSearchItem("Address", "Address", false) 9: .AddSearchItem("Phone", "Phone", false) 10: .SetDataUrl(Url.Action("ListContacts")) 11: .SetRecordsPerPage(10)
12: .SetHeight(300)
13: .SetWidth(600)
14: .Create("tablefx")%> 15: });
16: </script>
Flexigrid verrà quindi creata vuota lato client; una chiamata asincrona chiederà al server i dati in formato Json utilizzando l'url passato come fonte dati con
.SetDataUrl(Url.Action("ListContacts")).
Questo si traduce nella chiamata alla nuova action (creata ad hoc) ListContacts del nostro controller.
1: public ActionResult ListContacts(int page, int rp, string sortname, string sortorder, string query, string qtype)
2: { 3: }
Flexigrid chiamerà la nostra action indicando:
| Parametro |
Descrizione |
| page |
Pagina corrente |
| rp |
Record per pagina |
| sortname |
Colonna usata per l'ordinamento |
| sortorder |
Ordinamento ASC o DESC |
| query |
Testo da ricercare |
| qtype |
Colonna su cui eseguire la ricerca |
A questo punto abbiamo tutti i parametri necessari per implementare la nostra logica di interrogazione dati. Per inviare i dati al client creiamo due classi di supporto che useremo come DTO per popolare la nostra Flexigrid.
Definiamo prima di tutto il DTO per le righe
1: namespace FlexiGridTutorial.Models
2: { 3: public class FlexiGridDataRow
4: { 5: public string id;
6: public string[] cell;
7: }
8: }
ed uno per la visualizzazione corrente
1: using System.Collections.Generic;
2:
3: namespace FlexiGridTutorial.Models
4: { 5: public class FlexiGridData
6: { 7: public int page;
8: public long total;
9: public IList<FlexiGridDataRow> rows;
10: }
11: }
Anche in questo caso la scelta dei nomi dei datamember rispecchia quanto richiesto da Flexigrid in termini di notazione Json.
Il vantaggio di questo approccio è la semplicità del codice necessario a generare la nostra risposta Json:
1: public ActionResult ListContacts(int page, int rp, string sortname, string sortorder, string query, string qtype)
2: { 3: var data = new FlexiGridData();
4: data.rows = new List<FlexiGridDataRow>();
5: ...
6: return Json(data);
7: }
Finita l'infrastruttura implementiamo la logica di interrogazione utilizzando Linq a partire dalla nostra base dati.
1: // source data
2: IQueryable<ContactModel> db = SampleData.LotOfContacts;
Per prima cosa eseguiamo l'eventuale ricerca impostata dall'utente
1: // filter
2: if (!String.IsNullOrEmpty(query))
3: { 4: switch (qtype)
5: { 6: case "Name": db = from l in db where l.Name.ToLowerInvariant().Contains(query) select l; break;
7: case "Address": db = from l in db where l.Address.ToLowerInvariant().Contains(query) select l; break;
8: case "Phone": db = from l in db where l.Phone.ToLowerInvariant().Contains(query) select l; break;
9: }
10: }
memorizziamo quindi le informazioni per la paginazione (pagina corrente e numero totale di record)
1: // pagination data
2: data.page = page;
3: data.total = db.Count();
ed applichiamo il criterio di ordinamento:
1: // order
2: bool desc = String.Compare("desc", sortorder, true) == 0; 3:
4: switch (sortname)
5: { 6: case "Name": db = desc ? db.OrderByDescending(x => x.Name) : db.OrderBy(x => x.Name); break;
7: case "Address": db = desc ? db.OrderByDescending(x => x.Address) : db.OrderBy(x => x.Address); break;
8: case "Phone": db = desc ? db.OrderByDescending(x => x.Phone) : db.OrderBy(x => x.Phone); break;
9: }
Ora che la nostra query è pronta applichiamo la paginazione per limitare il numero di record da inviare al client:
1: // pagination
2: db = db.Skip((page - 1) * rp).Take(rp);
Non resta che creare i DTO da inviare al client
1: // result...
2: foreach (var contact in db)
3: { 4: var row = new FlexiGridDataRow
5: { 6: id = contact.ID,
7: cell = new[]
8: { 9: contact.Name,
10: contact.Address,
11: contact.Phone
12: }
13: };
14:
15: data.rows.Add(row);
16: }
ed inviare la risposta
1: // response
2: return Json(data);
Ed ecco la nostra griglia pronta all'uso...
Download code: FlexiGridTutorial03.zip (183kb)