Tag Archives: MVC

JSON sorosítás

Már régóta nyilvánvaló, hogy az AJAX a múlté, hiszen AJAJ van helyette. Kezdetben azért volt ez így, mert kín és szenvedés volt az XMLHttpRequest objektumot alacsonyszinten matatni, de aztán jött a jQuery és azóta minden rózsaszín. Az XML-t azonban teljesen jogosan leváltotta a JSON és azóta az Ajax elnevezés már nem is egészen helytálló.

Persze mióta mindenki JSON-t használ a kliens-szerver közötti kommunikációra, egyre gyakrabban merül fel a kérdés, hogy hogyan állítsunk elő szerver oldalon JSON-t és hogyan dolgozzuk fel a JSON-ban bejövő adatokat? .NET-ben szerencsére (?) van erre több lehetőség is:

Már az is elég szomorú, hogy egy frameworkön belül két osztály is szolgál ugyanarra, a nagyobb gond viszont az, hogy egyik sem tökéletes. Egyrészt sajnos mindkettőben vannak hibák, amik valahogy nem akarnak kijavulni több framework verzió óta, másrészt egyszerűen nem elég rugalmasak. Szóval rájuk férne egy kis pofozgatás, webfejlesztői szemmel mindenképp. Tudja ezt az ASP.NET MVC csapat is, csakhogy egyik névtér sem hozzájuk tartozik, így jár, aki out-of-band.

De kár szomorkodni, hiszen vannak kiváló megoldások a piacon, sőt a szabadpiacon! Ott van például a Json.NET osztálykönyvtár, ami már sok helyen bizonyított, ahol a beépített osztályok kevésnek bizonyultak. Ingyenes, rugalmas és még gyors is:

json-406-json-performance

Le a kalappal James Newton-King előtt, hogy egy ilyen hobbiból megírt és még szabadon elérhetővé is tette. Köszönjük.

Akkor most egy pillanatra képzeljük magunkat az MVC csapat helyébe: van egy funkció, ami nagyon kell, ám a beépített verzió nem ideális és nincs lehetőségük megjavítani, ámde van egy külső komponens, ami jónak tűnik. A külső komponensek amúgy is beváltak már ennél a csapatnál, elég csak a jQuery-re, jQuery Validationre és Modernizr-re gondolni, amik megjelennek a projekt sablonokban.

Hogy mi lesz a preferált megoldás az MVC4-ben, arról kár most találgatni (és amúgy se mondhatom meg az NDA miatt). Én mindenesetre azt mondom, aki JSONozik, annak ideje megismerni a Json.NET-et…

 

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

ASP.NET MVC 4 újdonságok 5 percben

logoHamarosan elérhető lesz az ASP.NET MVC 4 bétája, amit az ASPInsiders tagságnak köszönhetően már a múlt héten sikerült megszereznem. Nagyon sok kellemes újdonság van benne, közülük több is azonnal belopta magát a szívembe, ezért úgy döntöttem, hogy videó sorozatot készítek az újdonságokról. Pár részt már fel is vettem és amint feloldják az NDA-t, már teszem is ki őket a Youtube-ra.

Coming soon!

 

Technorati-címkék: ,,,

Ajaxos táblázatfrissítés ASP.NET MVC-ben JavaScript nélkül

A HTML5 Játéktér fejlesztésénél jött elő a feladat, hogy egy Ajax hívás után frissíteni kell egy táblázatot, pontosabban törölni kell egy sort belőle. Ha az adott sorban a felhasználó rákattint a Törlés gombra, akkor törölni kell a megfelelő rekordot a szerveren, majd a kliens oldalon a táblázatból is, természetesen teljes page postback nélkül. A jó hír az, hogy ezt ASP.NET MVC-ben egyetlen sor JavaScript írása nélkül meg lehet tenni.

Íme a view egy részlete, ami a táblázat egy sorát rendereli:

<tr id="game-@item.Slug">
  <td>
    @Ajax.ActionLink( "Törlés", "Delete", "Game",
      new { slug = item.Slug },
      new AjaxOptions
      {
        Confirm = "Biztos?", 
        InsertionMode = InsertionMode.Replace, 
        UpdateTargetId = "game-" + item.Slug
      },
      new { @class = "button delete" } )
  </td>
</tr>    

A lényeges részeket aláhúztam:

  • Minden sornak generálunk egy egyedi id attribútumot.
  • Az Ajax hívásnál megadjuk, hogy a szervertől érkező válasszal cserélje ki (InsertionMode) az egész sort (UpdateTargetId).

Ha a feladat az aktuális sor eltávolítása, akkor csak arról kell gondoskodnunk, hogy a szerver oldali controller action üres válasszal térjen vissza:

public ActionResult Delete( string slug )
{
  // Ide jön a törlés...

  return new EmptyResult();
}

 

Technorati-címkék: ,,

ASP.NET MVC remote validation

A model validation az egyik kedvencem az ASP.NET MVC-ben. Egy helyre kerül minden, ami a validáláshoz kell, ráadásul a jQuery validationnek köszönhetően a beépített “validátorok” nagyon jól működnek kliens oldalon is.

Legyen mondjuk egy klasszikus Person modell osztályunk, amire könnyen felaggathatom a validálási szabályokat leíró attribútumokat:

public class Person
{
    [DisplayName( "E-mail cím:" )]
    [Required( ErrorMessage = "Az e-mail cím megadása kötelező! ")]
    public string Email { get; set; }

    [DisplayName( "Felhasználónév:" )]
    [Required( ErrorMessage = "A felhasználónév megadása kötelező! " )]
    public string UserName { get; set; }

    [DisplayName( "Jelszó:" )]
    [Required( ErrorMessage = "A jelszó megadása kötelező! " )]
    public string Password { get; set; }
}

A view-ba pedig csak @Html.ValidationMessageFor hívások kellenek a hibaüzenetek megjelenítéséhez (amiket egyébként a VS le is generál magától):

@using( Html.BeginForm() )
{
    @Html.ValidationSummary( true )
    <fieldset>
        <legend>Regisztráció</legend>
        <div class="editor-label">
            @Html.LabelFor( model => model.Email )
        </div>
        <div class="editor-field">
            @Html.EditorFor( model => model.Email )
            @Html.ValidationMessageFor( model => model.Email )
        </div>
        <div class="editor-label">
            @Html.LabelFor( model => model.UserName )
        </div>
        <div class="editor-field">
            @Html.EditorFor( model => model.UserName )
            @Html.ValidationMessageFor( model => model.UserName )
        </div>
        <div class="editor-label">
            @Html.LabelFor( model => model.Password )
        </div>
        <div class="editor-field">
            @Html.EditorFor( model => model.Password )
            @Html.ValidationMessageFor( model => model.Password )
        </div>
        <p>
            <input type="submit" value="Mehet" />
        </p>
    </fieldset>
}

A helyzet akkor kezd bonyolódni, amikor kliens oldalon szeretnénk validálni, de az input ellenőrzési logika vagy a hozzá szükséges egyéb adatok szerver oldalon vannak, például egy adatbázisban. Még kellemetlenebb a helyzet, ha ráadásul nem is egyetlen mező értékét kell ellenőriznünk, hanem több adat együttállását kell vizsgálnunk. Ezt megoldhatnánk egy postback után a controllerben, de sokkal felhasználóbarátabb, ha Ajaxosan oldjuk meg, hiszen így már az űrlap kitöltése közben tudjuk figyelmeztetni a felhasználót, hogy javítsa ki a beírt értékeket. Szerencsére erre a problémára van közvetlen megoldás az ASP.NET MVC-ben, úgy hívják, hogy remote validation. Így kell beizzítani:

A modellben adjunk egy Remote attribútumot a validálandó mezőhöz:

[Remote( "ValidateUserNameAndEmail", "Home", AdditionalFields = "Email" )]
public string UserName { get; set; }

Itt meg kell adnunk, hogy melyik controller action lesz az Ajax hívás szerver oldali végpontja. Ha több mező értékére van szükségünk szerver oldalon, akkor használhatjuk az AdditionalFields paramétert. A fenti példában a validálás akkor fog megtörténni, amikor a UserName mező értéke megváltozik és a szerverhez el fog jutni az Email mező értéke is, az esetleges hibaüzenet pedig a UserName mező mellett fog megjelenni. Szerencsére semmi akadálya annak, hogy ugyanezt az attribútumot ráakasszuk az Email mezőre is, AdditionParameterkent a UserName mezőt adva meg.

Már csak a hivatkozott controller actiont kell megírnunk, például így:

[OutputCache( NoStore = true, Location = OutputCacheLocation.None )]
public JsonResult ValidateUserNameAndEmail( string userName, string email )
{
    return this.IsValid( userName, email ) ? 
        this.Json( true, JsonRequestBehavior.AllowGet ) : 
        this.Json( "Ezzel a névvel és e-mail címmel már létezik regisztráció!", 
            JsonRequestBehavior.AllowGet );
}

A valódi ellenőrző logikát áttettem egy IsValid függvénybe, hogy itt ne zavarjon. A lényeg:

  • Klasszikus controller action azokkal a paraméterekkel, amiket ellenőrizni szeretnénk. Ha van a modellben AdditionalFields, akkor mindet.
  • Válaszként egy JsonResult típussal kell visszatérnünk.
  • Ha az adat helyes, akkor a válasz true, ha hibás, akkor a hibaüzenet.
  • Meg kell adni a JsonRequestBehavior.AllowGet paramétert, anélkül nem fog menni.
  • Célszerű az OutputCache-t kikapcsolni, hogy a böngésző ne gyorsítótárazza a választ.

A hibaüzenet a Html.ValidationMessageFor helyén fog megjelenni, tehát a view-n nem kell változtatnunk. Ha nem a Studio generálta a markupot, hanem mi írtuk, akkor arra érdemes figyelni, hogy legyen benne Html.BeginForm, mezei <form> elemre tapasztalataim szerint nem működik.

Mindössze ennyi, az Ajaxos bűvészkedést az ASP.NET megcsinálja helyettünk. Íme az eredmény:

aspnet-mvc-remote-validation

Akit szeretné lerántani a leplet a varázslatról, az nézze meg a generált markupban a data-val-remote- attribútumokat és figyelje meg a HTTP forgalmat például Fiddlerrel. Érdemes!

 

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

Unable to find assembly Microsoft.IdentityModel

Dávid Zoli barátommal épp egy HTML 5-ös, MVC-s, Azure-os, Facebook és Live loginos projekten dolgozunk, ahol a bejelentkezést a Windows Azure AppFabric Access Control Service (a marketingesek úgy látszik karakterszám alapján kapják a fizetést) segítségével oldottuk meg. Mivel ez lényegében Windows Identity Foundation az alkalmazás szempontjából, ezért a WIF telepítését megúsztuk annyival, hogy a Microsoft.IdentityModel.dll-t szépen bemásoltuk a website bin mappájába. Éljen a bin deployment!

Ez szépen is működött, ám amint elkezdtük használni a blog storage-ot, az alábbi hibaüzenet fogadott:

Unable to find assembly ‘Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’.

Hasonló néha előfordul, de ez a hibaüzenet két ok miatt furcsa:

  1. Semmi nem változott, továbbra is ott csücsül pont ez a DLL a bin-ben.
  2. A hibaüzenet nem egy authentikációval vagy authorizációval kapcsolatos kódrészletnél jött, hanem egy Azure blobos RoleEnvironment.IsAvailable hívásnál.

A Windows Azure hibaelhárítási tippek között szerepel egy idevonatkozó is, miszerint telepítsem újra a WIF-et. Csakhogy én soha nem telepítettem és nem is szeretném!

Végül a megoldás az lett, hogy gacutil /i-vel bedobtuk a DLL-t a GAC-ba, ami a fejlesztői gépen megoldotta a hibát, de az éles környezetbe történő telepítésnél sajnos le kell mondanunk bin deploymentről Szomorú arc

 

ASP.NET MVC Controller template-ek testreszabása

Ha egy ASP.NET MVC projektben új controllert generálok, annak valami ehhez hasonló lesz az eredménye:

public class DemoController : Controller
{
  // 
  // GET: /Demo/

  public ActionResult Index()
  {
    return View();
  }
}

Biztos nem én vagyok az egyetlen (vagy igen?), akinek több dolog is bántja a szemét a kommenttel kapcsolatban:

  • A teljesen felesleges // komment sor.
  • A semmitmondó komment.
  • A komment utáni üres sor.

Egyébként rendben is van Mosolygó arc

Szerencsére az MVC csapat már dolgozik azon, hogy a következő verzióban a generált kód “normálisabb” legyen. Nem lesz felesleges komment sor és üres sor sem, sőt talán a generált komment is tartalmasabb lesz. ASPInsiderként javasoltam, hogy legyen XML komment, de az volt a válasz, hogy mivel controller metódusról van szó, azt vagy az MVC runtime hívja meg, vagy egy unit test és egyik helyen sem segítene az IntelliSense, ezért nem lesz XML komment. Végülis ebben van logika, egyébként meg az a fő cél, hogy kevesebb legyen a kód.

Szerencsére nem kell megvárnunk a következő MVC verziót, hogy javítsunk a generátoron, megtehetjük magunk. A generáláshoz használt T4 sablon itt található: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 3\CodeTemplates\AddController\Controller.tt

Ha ezt a fájlt átírjuk, akkor a gépünkön lévő összes MVC projekt az átírt változatot fogja használni.

Ha csak egy projektben szeretnénk más sablont használni, akkor a következő a teendő:

  1. A projektben létre kell hozni egy CodeTemplates és azon belül egy AddController mappát.
  2. Ide be kell másolni az előbb említett mappában található Controller.tt fájlt.
  3. A Solution Explorer ablakban be kell rá állítani, hogy Build Action = None.
  4. Át lehet írni a Controller.tt fájlt, ahogy jólesik.

Így végül csak lett XML kommentem és még source controlba is bekerült a sablon Mosolygó arc

 

Technorati-címkék: ,,,

Áttérés MVC 3-ra

Ahogy már korábban írtam róla, 10 napja megjelent az ASP.NET MVC 3 végleges változata. Az új verzió nagyon sok újdonságot tartalmaz, ezért nem is meglepő, hogy az előző verzióról történő átállás sem két kattintásos varázslós feladat. Szerencsére van néhány külső eszköz, amely segíthet ezt egyszerűbbé tenni.

Az egyik az ASP.NET MVC 3 Project Upgrade Tool, amellyel egy MVC 2 solution fájlt nyithatunk meg és migrálhatunk gyorsan MVC 3-ra. Az eszközt az ASP.NET csapat készítette, a működéséről részletesen Marcin Dobosz blogjában olvashatunk. Ugyanitt találunk útmutatót MVC 1 projektek frissítésére is.

Az egyik legnagyobb újdonság az MVC 3-ban (és egyébként az ASP.NET WebPages-ben is) a Razor view engine. Ám sajnos aki erre át akar állni, annak karakterről karakterre át kell írnia az ASPX oldalait, ami nem éppen szívderítő feladat. Ezen próbál segíteni Li Chen ASPX to Razor Converter projektje, amely a CodePlexen érhető el. Ez nem Microsoftos produktum, hobbiból készül, viszont a készítője előszeretettel használja is a saját projektjeiben, és saját bevallása szerint eddig elég jó eredményeket ért el. Egy próbát biztosan megér.

Aki mégis úgy dönt, hogy nem bízik a kitt-katt eszközökben és marad a kézi munkánál, annak mindenképpen célszerű elolvasnia az MVC 3 Release Notes-ban található Upgrading an ASP.NET MVC 2 Project to ASP.NET MVC 3 c. fejezetet, ahol pontosan leírják az áttérés lépéseit.

Technorati-címkék: ,