how create a single page apps using html5 and javascript

25
Javascript to IQueryable http://www.linqitalia.com/ricerca/super.aspx?action=author&key=Stefano+Marchisio http://Javascriptiqueryable.codeplex.com Stefano Marchisio http://Javascriptiqueryable.codeplex.com TorinoTechnologiesGrou p www.TorinoTechnologiesGrou p.it

Upload: stefano-marchisio

Post on 21-May-2015

2.030 views

Category:

Technology


3 download

DESCRIPTION

Create a html5/javascript apps with mvc/ajax using knockout.js/mvvm. Javascript to IQueryable is a framework that allows you to write a simple query in javascript client side and then execute it server side with EntityFramework or a linq provider that implement IQueryable. On the server is used "Dynamic Expressions and Queries in LINQ by Microsoft" to compose dynamically your query. In this way you can create a grid with filter, paging and sort functions. There is also support for: mvc3 unobtrusive jquery validation and jquery mobile/phonegap. - http://Javascriptiqueryable.codeplex.com - http://www.youtube.com/watch?v=qjwyKwsXHKs - http://www.linqitalia.com/articoli/entity-framework/sfruttare-javascript-eseguire-query-linq-server-tramite-dynamic-iqueryable.aspx

TRANSCRIPT

Page 1: How create a single page apps using html5 and javascript

Javascript to IQueryablehttp://www.linqitalia.com/ricerca/super.aspx?action=author&key=Stefano+Marchisio

http://Javascriptiqueryable.codeplex.com

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

TorinoTechnologiesGroup

www.TorinoTechnologiesGroup.it

Page 2: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Esistono situazioni in cui siamo “costretti” ad utilizzare in linguaggio Javascript in

alcuni parti delle nostre applicazioni.

1) PhoneGap applications2) MVC / Web applications

JavaScript e’ bello/brutto ???

Che ci piaccia o no ... In alcuni casi dobbiamo usarlo !!!

Windows 8 ? – Se uno conosce XAML e C# meglio evitarlo

Pertanto dobbiamo prendere confidenza con questo “signore”

( e’ come il vino: bere con moderazione !!!)

Page 3: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

L'introduzione di MVC ha cambiato l'approccio che abbiamo nello sviluppare le

nostre applicazioni; infatti se con le "webform" si fa largo uso dei "postback" (con i

vantaggi e gli svantaggi che essi comportano), con MVC non abbiamo piu' i

"postback" per cui dobbiamo sviluppare le nostre applicazioni dando un maggior

peso alla porzione di codice javascript presente nelle nostre pagine.

Page 4: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Una delle problematiche piu' comuni che si deve affrontare e' visualizzare una view

MVC al cui inteno c'e' del codice javascript che legge dei dati dal server in formato

"json" per poi paginarli (eventualmente applicando dei filtri su tali dati).

Infatti e' necessario:

1) Creare una chiamata rest in modalita' ajax.

2) Sul server ci deve essere un “action method“ che elabori la richiesta.

3) Il browser deve elaborare la risposta.

Cio’ comporta la scrittura di una certa dose di codice (da entrambe le parti) spesso ripetitiva. Come fare a non dover reinventare la ruota tutte le volte ?

Magari avendo la possibilita’ di poter effettuare delle query dinamiche ?

Page 5: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Iqueryable e’ potente, purtroppo accetta come parametro solo delle “lambda

expression” che per loro natura sono tipizzate per cui risulta difficoltoso poter

lavorare in modo dinamico (senza dover ricorrere ad ODATA).

Come risolvere il problema ?Siamo disposti a portare Iqueryable nel Controller ? Se si ...

Anche se non e' inclusa nel framework esiste una libreria scritta da Microsoft

"Dynamic Expressions and Queries in LINQ" con la quale e' possibile comporre delle

query in modo dinamico; infatti invece di usare le "lambda expression" all'interno

delle varie clausole (where, orderby e select) vengono usate della stringhe.

Page 6: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

var query = db.Customers.

Where("City = @0 and Orders.Count >= @1", "London", 10).

OrderBy("CompanyName").

Select("new(CompanyName as Name, Phone)");

Saranno poi i metodi di "Dynamic Expressions and Queries in LINQ" che parsando le stringhe inserite creano l' "expression tree" corrispondente.

Dynamic Expressions.html

Dynamic Expressions and Queries in LINQ

Page 7: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Requisiti del progetto

1) Poter effettuare delle query in cui linq e’ abilitato lato client (reqmessage).2) Poter effettuare delle query in cui linq non e’ abilitato lato client (querystring).3) Avere delle funzionalita' per la paginazione.4) Ottenere un risultato in formato dati json da manipolare poi sul client.5) Ottenere un risultato in formato dati html da manipolare poi sul client.6) Per i 2 punti precedenti avere la possibilita' di impostare dei template (client o server)7) Il tutto utilizzando una sintassi "metodo punto metodo" tipo jquery.

Page 8: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

(*) L’ oggetto RequestRest ha una serie di proprieta'/metodi tramite i quali posso impostare un mapping tra i parametri dell'url ed i campi dell ' entity al fine di poter comporre localmente la query

Page 9: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Demo

Page 10: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Contratti request (linq abilitato/linq non abilitato)var reqmessage = { "groupresult": value, "enablepaging": value, "where":{"value": "", "param": "", ptype: "" }, "order":{"value": "", "param": ""}, "select":{"value":"", "param": ""}, "skip": n, "take": n} a

url?currpage=n&currsize=n&param1=valore2&param2=valore2"&orderby=value

N.B. Nel caso linq non sia abilitato verra’ creato un url contente solo dei parametri, le varie clausole di select, where e orderby verranno create poi sul server.

Page 11: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Contratti response (comuni linq abilitato/linq non abilitato)

var resmessage = { "total": n, "records": n, "rows":[{},{}, ... ,{}] }

N.B. Il server puo' restituire sia dati grezzi che testo in formato html.

1) Se sono restituiti dati grezzi la proprieta' rows conterra’ un array di dati in formato “json“

2) Se sono restituiti dati testo in formato html la proprieta' rows (non sara' piu' un array) conterra' tali dati.

Page 12: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Riepilogando, a fronte dei 2 contratti utilizzati per le richieste (e di cio' che ci puo'

restiture il server json/html) esistono sostanzialmente 4 tipi di richieste e 2 tipi di

risposte.

1) context.linqEnabled = true;context.from("/Grid1/GetDataJson").where(" ... slide/succ ...").orderBy( "CustomerID").skip(3).take(6).applyTempClient();

2) context.linqEnabled = true;context.from("/Grid1/GetDataJson").where(" ... slide/succ ...").orderBy( "CustomerID").pagingWithSize(10).applyTempClient();

N.B. In entrambi i casi linq e' abilitato lato client (context.linqEnabled = true;)

GetDataJson?message={"groupresult":false,"enablepaging":true,"select":{"value":"","param":""},"order":{"value":"CustomerID","param":null},"where":{"value":"Country=@0","param":["spain"],"ptype":["str"]},"skip":0,"take":10}

Page 13: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

var index = 0; var where = "";var param = new Array(); if (text1!= "") { if (where != "") where = where + " and City = @" + index; else where = where + " City = @" + index ; param[index] = text1; index++;} if (text2 != "") { if (where != "") where = where + " and Country = @" + index; else where = where + " Country = @" + index; param[index] = text2; index++;} context.from("/Grid1/GetDataJson").where(where,param).orderBy("CustomerID"). pagingWithSize(10).applyTempClient();

Where clause/1

Page 14: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

context.beginWhere("and");if (text1!= "") { context.addWhereClauseStr( "City" , "=", text1); //context.addWhereClause( "City" , "=", text1);} if (text2 != "") { context.addWhereClauseStr("Country", "=", text2); //context.addWhereClause("Country", "=", text2);}var r = context.endWhere(); context.from("/Grid1/GetDataJson").where(r.value,r.param,r.ptype).orderBy( "CustomerID").pagingWithSize(10).applyTempClient();

Where clause/2

Page 15: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

3) context.linqEnabled = false;context.from("/Grid3/GetDataJson"). where(swhere). orderBy( “CustomerID") .skip(3).take(6).applyTempClient();

4) context.linqEnabled = false;context.from("/Grid3/GetDataJson"). where(swhere).OrderBy( “CustomerID") PagingWithSize(10).applyTempClient();

N.B. In entrambi i casi linq non e' abilitato lato client (context.linqEnabled = false;)

“/GetDataJson?pagecurr=n&pagesize=n&p1=valore2&p2=valore2&orderby=value “

La substringa “p1=valore2&p2=valore2” e’ passata tramite il metodo “where(swhere)”

Page 16: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Tra i requisiti iniziali abbiamo detto che si possono ottenere sia dati in formato

“json” che dati in formato testo “html”. L’ una o l’ altra opzione e’ gestita tramite il

metodo con cui si copleta la query lato client.

applyTempClient (“x")/applyTempServer(“x")

Page 17: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

(*) L’ oggetto RequestRest ha una serie di proprieta'/metodi tramite i quali posso impostare un mapping tra i parametri dell'url ed i campi dell ' entity al fine di poter comporre localmente la query

Page 18: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Esistono 2 tipi di richieste che possono arrivare sul server (linq abilitato/linq non

abilitato) per cui parametro presente sull'action method del controller e'

rappresentato da 2 oggetti distinti “RequestLinq” e “RequestRest”. Entrambe le

richieste devono invocare i metodi che effettuano la query, i quali necessitato che

venga passato come parametro l'oggetto presente sull'action method. Onde evitare

una duplicazione del codice sottostante ho creato un interfaccia "IRequestQuery"

che viene usata per invocare l' "extension method" di IQueryable

"JQuery(IRequestQuery)", che contiene la logica per lavorare con gli "expression

tree" al fine di poter comporre la nostra query. Inoltre tale interfaccia viene anche

implementata da "RequestLinq" e " RequestRest".

Page 19: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Visto che gli oggetti "RequestLinq" e " RequestRest" devono essere instanziati e popolati

con cio' che e' presente sull'url, e non andando bene il "ModelBinder" di default, ho

creato 2 ModelBinder custom: "ModelBinderLinqRequest" e "ModelBinderRestRequest"

(che mappano tali oggetti). In questo modo a fronte dei 2 tipi di richieste che possono

giungere sul server, sara' il ModelBinder custom associato al tipo di richiesta che mi crea

e configura il parametro dell'action method. Lavorando poi con un'interfaccia comune

"IRequestQuery" faccio in modo che cio' che c'e' sotto non sia influenzato dai 2 contesti

diversi di esecuzione.

Page 20: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Il metodo "JQuery(IRequestQuery)” e’ un extension method dell’ interfaccia

IQueryable ed accetta come parametro oggetti di tipo (RequestLinq/RequestRest).

Ritorna un oggetto managed con il seguente formato (la proprieta’ data contiene un

array di dati grezzi):

result = new { total = total, records = count, rows = data, };

Page 21: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

1) Link abilitato lato client e solo template lato client public ActionResult GetDataJson(RequestLinq linq){ var query = Repository.GetRepository<Customer>().Query(); return Json(query.JQuery(linq), JsonRequestBehavior.AllowGet); }

2) Link abilitato lato client e template lato client o lato server

public ActionResult GetDataJson(RequestLinq linq) { var query = Repository.GetRepository<Customer>().Query(); object data = this.TryApplyView(linq, query.JQuery(linq)); return Json(data, JsonRequestBehavior.AllowGet); }

Page 22: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Nel caso venga applicato un template lato server (una partialview) devo far ritornare solo il relativo contenuto html. Per far questo ci viene in aiuto l' "extension method" della classe "Controller“.

this.TryApplyView(par, query.JQuery(par))

Ritorna un oggetto managed con il seguente formato (la proprieta’ data contiene un array di dati grezzi oppure testo html):

result = new { total = total, records = count, rows = data, };

Page 23: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

L’ oggetto RequestRest ha una serie di proprieta'/metodi tramite i quali posso

impostare un mapping tra i parametri dell'url ed i campi dell ' entity al fine di poter

comporre localmente la query e fare quello che viene fatto nel browser per le query

in cui c'e' linq abilitato lato client. Cio’ mi permette di usufruire dell’interfaccia

comune IRequestQuery.

Page 24: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

3) Link non abilitato lato client e template lato client o lato server

public ActionResult GetDataJson(RequestRest rest) { rest.Operator = WhereOperator.And; rest.AddWhereMapping( "City“ , "=", "campo1"); rest.AddWhereMapping("Country", "=", "campo2"); rest.DefaultOrderBy("CustomerID"); var query = Repository.GetRepository<Customer>().Query(); object result = this.TryApplyView(rest, query.JQuery(rest)); return Json(result, JsonRequestBehavior.AllowGet); }

Page 25: How create a single page apps using html5 and javascript

TorinoTechnologiesGroup

Stefano Marchisio http://Javascriptiqueryable.codeplex.com

Demo