Ne várakoztasd a felhasználót: jQuery Templates és ASP.NET PageMethods

A webalkalmazásokkal szemben az egyik legfontosabb követelmény, hogy gyorsan jelenjen meg az eredmény a böngészőben, ami nem is gond, ha az oldalon kevés adat van. Probléma akkor van, ha az oldalra többféle adatforrásból jönnek az adatok, ekkor ugyanis előfordulhat, hogy egyetlen sokáig tartó adatbázis lekérdezés feltartja a teljes oldal renderelését, hiába jött meg a válasz a többi helyről villámgyorsan. Ekkor a legcélszerűbb megoldás, ha az oldal hamar elkészült részét gyorsan leküldjük a böngészőnek, a lassan előálló részt viszont aszinkron módon rendereljük ki. Hasonló megoldásra van szükség akkor is, amikor az oldal jelentős része output cache-ből jön, de egy kis részből mindig a legfrissebbet kell láttatnunk.

A problémát igazán nem is az aszinkronitás okozza, hiszen manapság már gyerekjáték egy Ajaxos hívást indítani a böngészőből. A gányolás ott kezdődik, amikor a nyers adatszerkezetből formázott HTML-t kell előállítani. Hol tegyük ezt meg: kliens oldalon vagy szerver oldalon? Egyáltalán hogyan lehet ezt kulturáltan megoldani, van jobb megoldás a sztring összefűzésnél?

Szerencsére van jobb megoldás: adatkötés. Jelentős mennyiségű ügyeskedéssel eddig is meg lehetett oldani, hogy szerver oldalon egy ASCX modult készítettünk, abban a szokásos módon szétválasztottuk a kódot és a megjelenést, majd a megszokott adatkötéssel HTML-lé alakítottuk és ezt a kész HTML-t küldtük le a böngészőnek. Ez így elsőre jónak is tűnik, de hamar elkezd több sebből vérezni.

A jó hír az, hogy most már lehet kliens oldalon is adatot kötni! Így nem kell szerver oldalon az adatok formázásával foglalkozni, gyorsan át lehet küldeni a nyers adatszerkezetet a kliensnek, a szép megjelenítésről pedig a böngésző fog gondoskodni. Nagyon vártam már ezt a pillanatot, ugyanis így jelentősen egyszerűsödni fognak az alkalmazásaink, sokkal karbantarthatóbb lesz a kódunk.

Van egy kis dezsavű érzésem, ugyanis ez már a harmadik alkalom, hogy ennek örülök. A Microsoft először 2007-ben próbálkozott a kliens oldali adatkötéssel, akkor XML Script formájában. Aztán azt mind elvetették, jött a Sys.UI.DataView, ami szintén ígéretesnek látszott, de végül az Ajax Library-vel az is ment a kukába. A mostani megoldást szintén a Microsoft kezdte el fejleszteni, de végül a jQuery csapat közreműködésével készült el és jQuery pluginként lett elérhető. Pontosabban két pluginről van szó, a jQuery Templates és a jQuery Data Link pluginekről, az előbbi az adatok megjelenítésére jó, az utóbbi pedig a kétirányú adatkötés megvalósítása. Bár nem ez az első deklaratív megvalósítás a sablon alapú renderelés és az adatkötés megoldására, a jQuery csapat végül úgy döntött, hogy ez lesz a hivatalos, és várhatóan az 1.5 verziótól kezdve az alap jQuery könyvtár részét képezik majd.

Mint a faék

Íme a jQuery Templates használata 4 egyszerű lépésben:

1. Legyen egy JavaScript objektumod az adatokkal:

  var movies = [
    { Name: "The Red Violin", ReleaseYear: "1998" },
    { Name: "Eyes Wide Shut", ReleaseYear: "1999" },
    { Name: "The Inheritance", ReleaseYear: "1976" }
  ];

2. Készíts hozzá egy sablont, ami fontos, hogy text/x-jquery-tmpl típusú script blokk legyen, így a böngésző figyelmen kívül fogja hagyni:

  <script id="myTemplate" type="text/x-jquery-tmpl">
    <li>
        <b>${Name}</b> (${ReleaseYear})
    </li>
  </script>

3. Keress egy placeholdert, ahol az eredményt meg akarod jeleníteni:

  <ul id="movieResults"></ul>

4. Renderelj:

  $("#myTemplate").tmpl(movies).appendTo("#movieResults");

Mondtam én, hogy nem bonyolult. Akárhogy is nézem, egyáltalán nem baj, hogy az előző próbálkozások mentek a levesbe, ez sokkal egyszerűbb és szebb. Az egyszerűségén kívül az tetszik benne nagyon, hogy a ${ } helyekre automatikusan HTML encoded értékek kerülnek. Ha nyers HTML-t, vagy JavaScriptet tartalmazó adataink vannak, akkor a {{html}} placeholdert kell használni. Ezen kívül lehet még a sablonba feltételeket tenni, sablonokat elnevezni és névvel hivatkozni rá és még pár dolgot, akit érdekel, nézze meg a teljes API leírást.

Szerver oldali kóddal

A fenti példa elég sok helyen megtalálható az interneten, de valljuk be, nem túl életszerű, hiszen az adatok többnyire inkább a szerverről jönnek. Ha ilyet szeretnénk, akkor legegyszerűbb az adatokat ASP.NET PageMethod segítségével publikálni:

  public class Movie
  {
    public string Name { get; set; }
    public int ReleaseYear { get; set; }
  }

  public partial class Step2 : System.Web.UI.Page
  {
    [WebMethod]
    public static Movie[] GetMovies()
    {
        return new Movie[]{
            new Movie(){ Name = "The Red Violin", ReleaseYear = 1998 },
            new Movie(){ Name = "Eyes Wide Shut", ReleaseYear = 1999 },
            new Movie(){ Name = "The Inheritance", ReleaseYear = 1976 }
        };
    }
  }

A gyönyörű ebben az, hogy a [WebMethod] attribútum hatására az ASP.NET automatikusan gondoskodik arról, hogy a válasz Movie[] JSON formátumra alakuljon (ha mégis manuálisan szeretnénk, akkor használhatjuk a JavaScriptSerializer osztályt).

Az így elkészült szerver oldali metódust nagyon egyszerű meghívni, elég csak feldobnunk az oldalra egy ScriptManagert és máris lesz egy JavaScriptből hívható PageMethods.GetMovies függvényünk. Persze ha úgyis jQuery-zni fogunk később, akkor logikusabb, ha ezt a PageMethodot is jQuery-ből hívjuk ScriptManager nélkül:

  $(function () {
    $.ajax({
        type: "POST",
        url: "Step2.aspx/GetMovies",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        success: function (result) {
            $("#myTemplate").tmpl(result.d).appendTo("#movieResults");
        }
    });
  });

Barátságos, nem? Sehol semmi extra kód a sorosításhoz vagy az alacsonyszintű HTTP kommunikációhoz. Egyetlen apró részletre kell figyelni, hogy a válaszban egy d objektumon belül lesznek az értékek. Ennek egyébként az a magyarázata, hogy ha az adatok között JavaScript kód is van, akkor az így nem tud véletlenül végrehajtódni.

Sokat egyszerre

Az Ajax lehetőségeinek bemutatására az egyik kedvenc példám a Pageflakes, mert gyönyörűen látszik, ahogy az oldal egyes részei önállóan betöltődnek. Kipróbáltam, hogy a fenti megoldás működik-e több párhuzamos kérésre is, vagy esetleg a browser connection limit miatt elhal valahol. Átírtam a kódot adatbázisosra és jó sok késleltetést tettem a szerver oldali kódba (így egyúttal azt is kipróbáltam, hogy egy List<T> sorosítása is megy magától), majd megnéztem, hogy mi látszik Firebugban (katt a képre a nagyobb változatért):

jQuery-PageMethods-Firebug

Látszik, hogy a böngészőnek valóban van párhuzamosítási korlátja, nálam a Firefox hatosával küldte el a kéréseket a szerverre. Szerencsére mindez ment teljesen automatikusan, a placeholderekbe tett animáló gifek pörögtek, ahogy kell, így még a felhasználó is kapott visszajelzést.

Ha ehhez a gördülékeny implementációhoz még az OData-t is hozzávesszük, akkor látszik, hogy végre kezdenek összeérni a technológiák, vége a trükközésnek.

Technorati-címkék: ,,,
Advertisements

One thought on “Ne várakoztasd a felhasználót: jQuery Templates és ASP.NET PageMethods

  1. Visszajelzés: Golyóálló Ajax hívások « Balássy György szakmai blogja

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s