files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/tanári+megosztások/bír…  · web...

82
ASP.NET MVC TUTORIÁL Szombat Sándor

Upload: trinhdat

Post on 07-Feb-2018

213 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

ASP.NET MVC TUTORIÁL

Szombat Sándor

Page 2: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Tartalom1. Kezdetek......................................................................................................................................................................3

Új alkalmazás létrehozása...........................................................................................................................................3

2. Kontroller készítése.....................................................................................................................................................8

3. Nézet készítése..........................................................................................................................................................14

A nézet és a layout megváltoztatása.........................................................................................................................18

Adatok átadása a vezérlőből a nézetnek...................................................................................................................22

4. Modell.......................................................................................................................................................................24

Modell létrehozása....................................................................................................................................................24

5. Connection String és SQL szerver..............................................................................................................................26

Connection String......................................................................................................................................................26

SQL Szerver Express Local DB....................................................................................................................................26

6. Hozzáférés a modell adatokhoz a vezérlőből............................................................................................................29

Movie létrehozása.....................................................................................................................................................30

A generált kód...........................................................................................................................................................32

Erősen típusos modellek és a @model kulcsszó........................................................................................................32

Munka az adatbázissal...............................................................................................................................................34

7. Az Edit metódus és az Edit nézet...............................................................................................................................37

POST kérés kezelése..................................................................................................................................................42

8. Keresés......................................................................................................................................................................45

Műfaj szerinti keresés...............................................................................................................................................49

Nézet módosítása......................................................................................................................................................51

9. Új mező hozzáadása..................................................................................................................................................52

Code First Migration beállítása..................................................................................................................................52

Rating mező hozzáadása a Movie modellhez............................................................................................................57

10. Validálás..................................................................................................................................................................64

Szabály hozzáadása a modellhez...............................................................................................................................64

Validation Error UI az ASP .NET MVC-ben.................................................................................................................66

Hogyan is néz ki a validálás a Create View és a Create action metódusban?............................................................67

DataType attribútum.................................................................................................................................................70

11. Details és Delete metódusok...................................................................................................................................71

2

Page 3: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

1. Kezdetek

Elsőként szükségünk van a Visual Studio Express 2013 for Web változatára, vagy pedig egy szimpla Visual Studio 2013- ra. Korábbi verziók is megfelelnek erre, amennyiben képesek webalkalmazás létrehozására.

A Visual Studio egy intergrált fejlesztői környezet (IDE).Hasonlóan, mint ahogy a Microsoft Word nevű programját használjuk dokumentumok létrehozására, ezt az IDE-t kell használnunk alkalmazások létrehozására. A Visual Studio megannyi különböző megoldással segíti a fejlesztés gyorsítását, és hatékonyabbá tételét.

Új alkalmazás létrehozása

A Visual Studio főablakának bal szélén található New project... felirat, amire kattintva feldob egy ablakot, ahol kiválaszthatjuk, milyen projectet szeretnénk létrehozni.

3

Page 4: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Ezután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd a ASP.NET Web Application-t. Nevezd el, ahogy gondolod (a példában MvcMovie a neve), majd add meg az elérési útját, és OK.

4

Page 5: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Ezután felugrik egy ablak (New ASP.NET Project), azon belül válaszd az MVC-t, majd OK.

A Visual Studio készített egy sablon ASP.NET MVC projectet, anélkül, hogy bármit is csináltál volna. Ez csak egy szimpla Hello World! alkalmazás, de kiindulási alapnak a legjobb.

5

Page 6: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Nyomd meg az F5-öt, elindítva a debugolást. Ekkor lényegében a Visual Studio elindítja az IIS Express-t, ami futtatja a web alkalmazásunkat (a Visual Studio tartalmaz egy mini webszervert, az IIS egy egyszerűsített változatát, ami azért is jó, mert így fejlesztéskor nem kell feltölteni egy konkrét szerverre a projectet, és semmi különösebb beállítást nem igényel, így megkönnyítve a fejlesztés menetét).Ezután megnyílik a böngészőnk, ahol megjelenik a sablon web alkalmazásunk. Ha megnézzük a címsort, akkor azt láthatjuk, hogy localhost:port#, nem pedig azt, hogy example.com/etc. Ez azért van, mert a localhost mindig a saját gépedre mutat, és amikor a Visual Studio futtatja a web alkalmazásunkat, egy random portot rendel hozzá. Ez a lenti képen 1234, de ez futásonként változhat.

Ez a sablon ad egy menüt is, pár aloldarra hivatkozva. A lenti képen ez nem látszik, mivel reszponzívra van megírva, így függ a böngésző méretétől is. Amennyiben nem látszik, a jobb felső sarokban található gombbal érhetőek el a menüelemek.

6

Page 7: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

A példában ezen kívül meg van írva egy regisztrációs felület és login rész is. A következő részben arról lesz, hogyan változtathatjuk meg a weboldal működését, és megismerkedünk kicsit az ASP.NET MVC-vel.

2. Kontroller készítéseAz MVC jelentése ugye modell-view-controller, vagyis modell-nézet-vezérlő. Az MVC lényegében egy minta az alkalmazások fejlesztéséhez, ami jól szervezett, tesztelhető, és könnyen kezelhető. Az MVC alapú alkalmazások tartalmaznak:

Modelleket: Osztályok, amik reprezentálják az adatokat az alkalmazáshoz, gondoskodnak az adatok helyességéről és "kikényszerítik" az üzleti szabályokat ezekhez az adatokhoz.

Nézeteket (Views): Sablon fileok, amik az alkalmazás kinézetét határozzák meg. Vezérlők (Controllers): Osztályok, amik kezelik a böngészőtől érkező adatokat, kinyerik a szükséges

adatokat a modellekből, beállítják a sablon nézeteket ezek alapján az adatok alapján, majd visszaküldik a választ a böngészőnek.

Látni fogunk mindre példát a későbbiekben és arra is, hogyan használjuk ezeket.

Először is készítsünk egy vezérlőt. A Solution Explorer-ben jobb klikk a Controllers mappán, majd Add, azon belül pedig válasszuk a Controllert.

7

Page 8: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Az Add Scaffold ablakban kattintsunk a MVC 5 Controller - Empty-re.

Nevezd el az új controlleredet HelloWorldController-nek.

Láthatod a Solution Explorer-ben, hogy létrejött az új file HelloWorldController.cs néven, illetve létrejött egy HelloWorld könyvtár a Views mappában. Az új kontrolleredet láthatod az IDE-ben megnyitva.

8

Page 9: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Cseréld ki a fájl tartalmát a következő kódra:

using System.Web;using System.Web.Mvc;  namespace MvcMovie.Controllers {     public class HelloWorldController : Controller     {         //         // GET: /HelloWorld/          public string Index()         {             return "This is my <b>default</b> action...";         }          //         // GET: /HelloWorld/Welcome/          public string Welcome()         {             return "This is the Welcome action method...";         }     } }

A kontroller metódusainak egy HTML szöveggel kell visszatérniük. A kontrollerünk neve HelloWorldController és az első metódusa ő metódusa az Index nevű metódus. Nézzük meg a böngészőben ezt. Futtassuk az alkalmazást (F5). A böngészőben láthatjuk, hogy a címsorhoz hozzáfűzte a kontrollerünk nevét (HelloWorld). A fenti metódusunk egy HTML szöveggel tért vissza, amit a böngésző meg is jelenített.

9

Page 10: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Az ASP.NET keretrendszer különböző controller osztályokat használ, illetve azokban különböző metódusokat az URL-től függően. A következő logikán alapszik:

/[Controller]/[ActionName]/[Parameters]

A routing formáját az App_Start/RouteConfig.cs nevű fileban határozhatod meg.

public static void RegisterRoutes(RouteCollection routes){    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(        name: "Default",        url: "{controller}/{action}/{id}",        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }    );}

Ha az alkalmazás fut, de nincs mellette semmilyen URL szegmens, ami meghatározná a kontrollert, akkor az alapértelmezett kontroller Index metódusa fut le.

Az URL elő része meghatározza a kontrollert osztályt. A következő rész meghatározza az abban található metódust. Szóval a HelloWorld/Index URL-nél a HelloWorld kontroller Index metódusa fog lefutni. Ha nem írjuk le, csak az első szegmensét, szóval a kontrollert, akkor alapértelmezetten annak az index metódusa fog lefutni. Ez minden kontroller alapértelmezett metódusa, ha nem definiálunk másikat, viszont emiatt ezt kötelező is definiálni. A harmadik része az URL szegmensnek az adatok. Erről később esik szó.

Így ha a HelloWorld/Welcome URL-t futtatjuk a Welcome metódus fut le és kiírja, hogy This is the Welcome action method...

10

Page 11: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Módosítsuk a példánkat, h ogy képesek legyünk paramétereket is fogadni az URL-ből (pl /HelloWorld/Welcome?name=Scott&nutimes=4). Írjuk át a Welcome metódust a következő módon. A metódus fejrészében azt is megmondjuk, hogy ha a nuTimes paramétert nem kapjuk meg, alapértelmezett értéke legyen 1:

public string Welcome(string name, int numTimes = 1) {     return HttpUtility.HtmlEncode("Hello " + name + ", NumTimes is: " + numTimes);}

Megjegyzés: A fenti kód a HttpUtility.HtmlEncode metódust használja, ami megvédi a alkalmazást a káros inputtól. Több információért olvasd el ezt a cikket!

Futtassuk az alkalmazásunkat, a következő URL-el: http://localhost/HelloWorld/Welcome?name=Scott&nutimes=47Próbálkozz különböző értékekkel a query stringben, az MVC megfelelő modulja automatikusan kezeli ezt, és a megfelelő paraméterekkel meghívja a nekünk kellő függvényt.

A fenti példában nem használjuk az URL szegmens paraméter részét, az adatok a query string-en keresztül kerülnek átadásra. A ? az URL szeparátor, és az & jel szeparálja el a különféle query részeket.

Cseréljük ki a Welcome metódust a következőre:

public string Welcome(string name, int ID = 1){    return HttpUtility.HtmlEncode("Hello " + name + ", ID: " + ID);}

11

Page 12: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Futtassuk az alkalmazásunkat, majd írjuk be a következő URL-t: http://localhost:xxxx/HelloWorld/3?name/rick

Most a harmadik URL szegmens passzol az általunk a route résznél megadott ID paraméterre. A Welcome metódus ID paramétere pontosan passzol a RegisterRoutes metódusban specifikált URL-hez.

public static void RegisterRoutes(RouteCollection routes){    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(        name: "Default",        url: "{controller}/{action}/{id}",        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }    );}

Általában az ASP.NET MVC-s alkalmazásainkban route adatként adjuk át a paramétereket query string helyett. Így átadható a name és a numtime paraméter is mint egy route adat az URL-ben. Ehhez az App_Start\RouteConfig.cs filet kell szerkesztenünk az alábbi módon:

public class RouteConfig{   public static void RegisterRoutes(RouteCollection routes)   {      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

      routes.MapRoute(          name: "Default",          url: "{controller}/{action}/{id}",          defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }      );

      routes.MapRoute(           name: "Hello",           url: "{controller}/{action}/{name}/{id}"       );   }}

12

Page 13: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Futtassuk az alkalmazásunkat a következő URL-el: http://localhost:xxxx/HelloWorld/Welcome/Scott/3.

Sok alkalmazásunknak bőven elég az alapértelmezetten definiált útvonal. Később esik majd szó arról, hogyan adjunk át adatokat a model kötésen keresztül, akkor nem is kell az alapértelmezett route-ot módosítanunk.

3. Nézet készítéseEbben a részben a HelloWorldController osztályt módosítjuk úgy, hogy sablon nézetek használunk, így totálisan jól egységbe tudjuk zárni a HTML készítését.

Sablon nézeteket készítésére a Razor view engine használható. A sablonoknak, amiket ezzel készítünk a kiterjesztése .cshtml lesz, illetve egy elegáns megoldást kínál arra, hogy HTML kimenetet generáljunk C# használatával. A Razor segítségével gyorsan, minimális és jó sablonokat tudunk készíteni.

Most jelenleg az Index metódusunk egy HTML szöveggel tér vissza, ami nem követi épp az MVC szabályait. Írjuk át úgy, hogy az egy View objektummal térjen vissza:

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

A fenti Index metódusunk ezután egy nézet sablon segítségével generálja a HTML választ a böngészőnek. A vezérlő metódusok (más néven action metódusok), akár csak a fenti Index metódusunk általában egy ActionResult típúsú objektummal (vagy abból származtatott típussal) térnek vissza, nem primitív típusokkal, mint a string.

Jobb klikk a Views\HelloWold mappán, Add, majd pedig MVC 5 View Page with (Layout Razor).

13

Page 14: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

A Specify Name for Item ablakban nevezzük el Index-nek.

A Select a Layout Page ablakban, fogadjuk el az alapértelmezetten választott _Layout.cshtml-t.

A fenti kép bal oldalán a Views\Shared van kiválasztva. Ha valami saját layout-od van egy másik mappában, azt itt is megtalálod. Erről majd később esik szó részletesen.

Mint az alábbi ábra is mutatja, a fájlunk létrejött:

14

Page 15: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Nyissuk meg a fájlunkat, és az alábbi kiemelt részt adjuk hozzá a kódhoz:

@{ Layout = "~/Views/Shared/_Layout.cshtml";}

@{ ViewBag.Title = "Index";}

<h2>Index</h2>

<p>Hello from our View Template!</p>

Kattintsunk jobb gombbal a fájlunkra, és válasszunk a View in Browser opciót.

15

Page 16: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Ezután a vezérlőnket a szokott URL-en keresztül nyissuk meg (http://localhost:xxxx/HelloWolrd). Az index metódusunk nincs is konkrétan más feladata, csak lefuttatja a return View(); utasítást, ami meghatározza, hogy a sablon nézetünk fogja előállítani a kimenetet. Mivel nem mondtuk meg pontosan, melyik sablont használja, így az AS.NET MVC alapértelmezetten az Index.cshtml-t fogja használni. A lenti kép mutatja az eredményt:

Mint láthatjuk az oldal title-je a lapoknál Index - My ASP.NET Application illetve a Fenti menüsorban az Application name látható. Mivel az oldal alapstílusa reszponzív, így ebben a menünek a három csíkra kattintva érhetjük el. Az ott

16

Page 17: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

található példák is még angolul vannak.

A nézet és a layout megváltoztatása

Az első, hogy megváltoztassuk az Application name feliratot. Ez jelenleg csak egy helyen van megírva a projektünkben, és ettől függ minden oldalunk. Keressük meg a /Views/Shared mappát, azon belül pedig nyissuk meg a _Layout.cshtml fájlunkat. Ezt nevezzük layout oldalnak, és a shared mappában van, mert minden oldalunk használja.

A layout sablonok határozzák meg az oldal keretének a kinézetét lényegében, minden nézet oldalunkat ebbe fog beszúrni. Keressük meg a @RenderBody() sort. Itt történik az általunk megírt nézet beszúrása az layout keretünkbe.

17

Page 18: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Változtassuk meg a title elem tartalmát. Ezen felül az ActionLink részt is Application nam-ről MVC Movie-ra és az Home részt írjuk át Movie-ra. A teljes layout file ezután így néz ki:

<!DOCTYPE html><html><head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - Movie App</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr")

</head><body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("MVC Movie", "Index", "Movies", null, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("Contact", "Contact", "Home")</li> </ul> @Html.Partial("_LoginPartial") </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div>

@Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false)</body></html>

18

Page 19: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Futtassuk az alkalmazásunkat. Most már a láthatjuk, hogy azt írja ki, MVC Movie. Kattintsunk az About részre, és láthatjuk, hogy ugyan azt írja ki. Csak egy helyen kellett változtatnunk, de az hatással volt az összes oldalunkra.

Amikor lekreáltuk az Index.cshtml fájlt, akkor csak az alábbi kódot tartalmazta:

@{ Layout = "~/Views/Shared/_Layout.cshtml";}

A Razor kód definiálta a layout oldalunkat. Ha megnézzük a Views\_ViewStart.cshtml fájl is tartalmazza ugyan ezt a részt. Lényegében ez a fájl határozza meg a többi oldalunk kinézetét. Szóval ezt a részt akár törölhetnénk is az Index.cshtml fájlból, akkor is az adott layoutot használná.

@*@{ Layout = "~/Views/Shared/_Layout.cshtml";}*@

@{ ViewBag.Title = "Index";}

<h2>Index</h2>

<p>Hello from our View Template!</p>

Használd a Layout tulajdonságot, hogy megváltoztasd a layoutot, vagy állítsd null-ra, ha nem szeretnéd meghatározni.

Változtassuk meg az Index nézetünk title részét.

19

Page 20: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Nyisd meg a MvcMovie\Views\HelloWorld\Index.cshtml fájlt. Két helyen kell változtatnunk: az egyik a böngésző title része a másik pedig az oldal header (<h2> tag része).

@{ ViewBag.Title = "Movie List";}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

Ha megnézzük a layout sablonunkat (Views\Shared\_Layout.cshtml), akkor láthatjuk, hogy a title rész az előbb beállított ViewBag objektum Title mezőjétől függ.

<!DOCTYPE html><html><head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - Movie App</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr")</head>

A ViewBag osztályt használva tudunk különféle paramétereket átadogatni a sablon nézetünk és a layout fájlunk között.

Futtassuk az alkalmazásunkat. Láthatjuk, hogy az elsődleges és másodlagos header-je változott. (Ha mégsem látnál változást, akkor előfordulhat, hogy a nézetet a gyorsítótárból (cache) olvasott ki bizonyos részeket a böngésző. Nyomj Ctrl+F5-öt a böngészőben! Ilyenkor kikényszeríted, hogy mindent töltsön le újra.) A böngésző title része inicializálva lett a ViewBag.Title segítségével, ezt elhasználva az Index.cshtml sablonunkban is, ezen felül a layout fájlban hozzáfűződött a "- Movie App" rész is.

Ezen felül látszik, hogy az Index.cshtml sablonunk és a _Layout.cshtml sablonunk összefűzésre került. Így a böngésző felé már csak egy, szimpla HTML lap lett küldve. A layout sablonok egyszerűvé teszik azt, hogy különböző részekből építsük fel a weblapokat, de a fix részeket elég csak egyszer definiálnunk.

20

Page 21: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Ha megnézzük, a kiért üzenetünk lényegében a kódba van égetve. Van már nézetünk (V), van már vezérlőnk (C) már csak a modell hiányzik. Nem sokára erre is rátérünk.

Adatok átadása a vezérlőből a nézetnek

Mielőtt viszont a modelleket kezdenénk jobban megvizsgálni, Meg kell nézzük, hogyan tudunk adatokat átadni a nézeteknek a vezérlőből. A vezérlőket az URL kérések feldolgozására használjuk. Kezelik a böngészők kéréseit, kinyerik az adatokat a modellek segítségével, és az éppen szükséges nézetet használva kiküldik a választ a böngészőnek.

A vezérlő feladata, hogy biztosítsa a nézetnek azokat az adatokat vagy objektumokat, amikre szüksége van ahhoz, hogy a böngészőnek előtudja állítani a választ. A legjobb, amikor a nézet sose kommunikál az adatbázissal, csak azokkal az adatokkal dolgozik, amiket a vezérlőtől kapott. Ha ezeket betartjuk, tesztelhető és kezelhető kódot kapunk.

Jelenleg a vezérlőnk kap két paramétert (name,numTime) és ezeket direktbe meg is jeleníti a böngészőnek. Írjuk át úgy, hogy ne a vezérlő állítsa elő a választ, hanem a nézetet használja erre a célra. A nézet egy dinamikus választ generál, ami annyit jelent, hogy a vezérlőből át kell adnod a nézetnek az adatokat, hogy meg tudja őket jeleníteni. Ebben a ViewBag objektum fog nekünk segíteni.

Nyissuk meg a HelloWorldController.cs fájlt, és írjuk át úgy a Welcome metódust, hogy képes legyen a kapott paramétereket átadni a nézetnek. Lényegében a ViewBag objektumon keresztül bármit átadhatunk, amit nem definiáltunk előre bármilyen névvel (persze megtartva a C# nyelv elnevezési szabályait). Például a ViewBag objektumnak nincs előre definiált numTimes tulajdonsága, de mi magunk definiálhatjuk ezt. Ez az ASP.NET MVC modell kötés rendszere. A módosított kód így néz ki:

using System.Web;using System.Web.Mvc;

namespace MvcMovie.Controllers{ public class HelloWorldController : Controller { public ActionResult Index() { return View(); }

public ActionResult Welcome(string name, int numTimes = 1) { ViewBag.Message = "Hello " + name; ViewBag.NumTimes = numTimes;

return View(); } }}

Most már a ViewBag objektum tartalmazza azokat az adatokat, amiket át szeretnénk adni a nézetünknek. Szükségünk van most egy Welcome sablonra. A korábban ismertetett módon hozzuk létre ehhez a nézetet, Welcome néven.

21

Page 22: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Írjuk át a Welcome.cshtml fájlt az alábbi módon:

@{ ViewBag.Title = "Welcome";}

<h2>Welcome</h2>

<ul> @for (int i = 0; i < ViewBag.NumTimes; i++) { <li>@ViewBag.Message</li> }</ul>

Így annyiszor írja ki a köszöntést, amennyiszer azt paraméterként megadtuk.

Futtassuk az alkalmazásunkat a következő URL-el:

http://localhost:xxxx/HelloWorld/Welcome?name=Scott&numTimes=4

22

Page 23: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Most a megadott paraméterek a vezérlőn keresztül eljutnak a nézethez a modell kötés segítségével.

A fenti példában a ViewBag segítségével küldünk adatokat a vezérlőből a nézetnek. Később majd használni fogjuk a "view model"-t is adatok átadására. Ez a blog bejegyzés részletesen leírja, mi a különbség a kettő között.

4. ModellEbben a részben megtanuljuk, hogyan tudunk modelleket létrehozni az alkalmazásunkban. Ezek fogják majd az adatbázisunkat kezelni.

Modell létrehozása

A Solution Explorer-ben, jobb klikk a Models mappára, ADD és válasszuk a Class-t.

23

Page 24: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Nevezzük el Movie-nak.

Adjuk hozzá az alábbi öt property-t az osztályunkhoz:

using System;

namespace MvcMovie.Models{ public class Movie { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } }}

A Movie osztályunk fogja reprezentálni a filmeket az adatbázisban. Minden egyes Movie példány egy sorral egyezik meg az adatbázisban, és minden egyes property a Movie osztályban egy oszlopot reprezentál.

Ugyan abban a fileban, adjuk hozzá a MovieDBContext osztályt:

using System;using System.Data.Entity;

namespace MvcMovie.Models{ public class Movie { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } }

public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } }}

A MovieDBContext osztály reprezentálja az Entity Framewok movie adatbázisát. Ez menedzseli az adatok kinyerését, tárolását, és frissítését az adatbázisban. Őse a DbContext osztály, amelyet az Entity Framework biztosít.

A következő sort kell hozzáadnunk a using részhez ahhoz, hogy tudjuk ezt az osztályt használni:

using System.Data.Entity;

24

Page 25: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

5. Connection String és SQL szerver

Connection StringA MovieDBContext osztály segít menedzselni a kapcsolódást és a Movie rekord adatbázisban való leképezését. A Kérdés az, hogyan mondjuk meg neki, hogy milyen adatbázist is használunk? Ezt az Entity Framework elvégzi helyettünk. Amit erre használ az a LocalDB

SQL Szerver Express Local DBA LocalDB az Sql Server Express változatának egy egyszerűsített változata. A Visual Strudi-val együtt települ, és használható fejlesztés közben. Lényegében az általunk készített adatbázist .mdf fájlba menti el.

Az Entity Framewok alapértelmezetten a connection string-nek azt a nevet adja, mint a context objektumunk (MovieDBContext). Bővebb leírás itt.

Nyissuk meg az alkalmazásunk főkönyvtárában lévő Web.config fájlt (nem a View mappában lévőt).

Keressük meg a <connectionString> elemet:

Adjuk hozzá a következő connection string-et a <connectionString> részhez a Web.config fájlban:

<add name="MovieDBContext"    connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Integrated Security=True" 

25

Page 26: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

   providerName="System.Data.SqlClient" />

Ezután így fog kinézni a Web.config fájlunk:

<connectionStrings>    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-MvcMovie-20130603030321.mdf;Initial Catalog=aspnet-MvcMovie-20130603030321;Integrated Security=True" providerName="System.Data.SqlClient" />    <add name="MovieDBContext"    connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Integrated Security=True" providerName="System.Data.SqlClient"/>

A két connection string meglehetősen hasonló. A DefaultConnection azt kezeli, hogy ki férhet hozzá az alkalmazásunkhoz. Amit mi hozzáadtunk, az később az App_Data mappában fog tárolódni. Az alapértelmezett adatbázist ebben a tutoriálban nem használjuk, de itt több infót találtok róla.

Fontos, hogy a connection string nevének meg kell egyeznie a DbContext nevével.

using System;using System.Data.Entity;

namespace MvcMovie.Models{    public class Movie    {        public int ID { get; set; }        public string Title { get; set; }        public DateTime ReleaseDate { get; set; }        public string Genre { get; set; }        public decimal Price { get; set; }    }

    public class MovieDBContext : DbContext    {        public DbSet<Movie> Movies { get; set; }    }}

Igazából erre a connection string-re nincs is szükség. Ha nem adjuk hozzá, akkor megteszi magától az Entity Framewok.

26

Page 27: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

6. Hozzáférés a modell adatokhoz a vezérlőbőlMielőtt bármit is tennénk, nyomjunk rá Build-re. Ha nem fordul le az alkalmazásunk, kapunk egy hibát, hogy létre kell hoznunk egy vezérlőt.

A Solution Explorer-ben jobb klikk a Controllers mappán, ADD majd Controller.

Az Add Scaffold részben válasszuk a MVC 5 Controller with View, using Entity Frameworkopciót, majd ADD.

A vezérlő neve legyen MoviesController Válasszuk ki a Movie (MvcMovie.Models)-t, szóval a kész modellünket Válasszuk ki a MovieDBContext (MvcMovie.Models)-t, a context osztálytunkat

27

Page 28: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Katt az ADD-ra. A Visual Studio legenerálja az alábbi fájlokat és könyvtárakat:

MoviesController.cs fájl Views\Movies mappa Create.cshtml, Delete.cshtml, Detail.cshtml, Edit.cshtml és Index.cshtml a fent említett mappában.

A VS automatikusan legenerál pár metódust (ceate, read, update, delete) és a nézetünket. Most, hogy van egy teljes értékű web alkalmazásunk, dolgozzuk ki a nekünk kellő metódusokat.

Futtassuk az alkalmazásunkat a következő URL-el: http://localhost:xxxx/Movies. Mivel nem állítottuk be a route-olást, így az alapértelmezett Index metódus fut le. Ez egy üres listát fog kiadni a filmjeinkről, mivel még egyet sem adtunk hozzá.

Movie létrehozásaKattintsunk a Create new hivatkozásra az oldalunkon. Kapunk egy felület, ahol adjunk meg pár részletet az adott movie-ról:

28

Page 29: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Megjelzés: jelen esetben nincs úgy megírva a program, hogy a "Price" mezőt működjön rendesen nem angol formátumú törtekre. Ahhoz, hogy ez működjön, használnunk kell egy jQuery plugint, méghozzá a globalize.js-t. Erre később ki fogok térni, hogyan kell ezt használni.

Ha a Create gombra kattolunk, akkor az adatokat elküldjük a szerver felé. Ott bekerül az adatbázisba, majd a listára irányítódik át az oldalunk, ahol látjuk az imént bevitt movie tulajdonságait.

Írjunk be minél több filmet, és teszteljük a szerkesztést, törlést is, láthatjuk, hogy mint működőképes.

29

Page 30: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

A generált kódNyissuk meg a COntrollers\MoviesController.cs fájlt, és vizsgáljuk meg a generált Index metódust:

public class MoviesController : Controller{ private MovieDBContext db = new MovieDBContext();

// GET: /Movies/ public ActionResult Index() { return View(db.Movies.ToList()); }

A Movies konrtoller a lényegében a Movies tábla összes sorát átadja megjelenítésre a nézetünknek. Az alábbi sorunk csinál egy példányt a már korábban ismertetett MovieDBContext osztályunkból. Ezt használhatjuk lekérésre, módosításra, törlésre, beszúrásra.

private MovieDBContext db = new MovieDBContext();

Erősen típusos modellek és a @model kulcsszóKorábban láthattuk, hogyan adjunk át a vezérlőből adatot a nézetnek. A ViewBag-et használtuk erre, ami egy dinamikus objektum.

Az MVC lehetőséget ad arra is, hogy erősen típusos adatokat adjunk át a nézetnek. Ez gyorsabb fordítási időt eredményez.

A Controllers\MoviesCOntroller.cs fájlunkban hozzuk létre a Details metódust az alábbi módon:

public ActionResult Details(int? id){ if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Movie movie = db.Movies.Find(id); if (movie == null) { return HttpNotFound(); } return View(movie);}

Az id alapvetően úgy lesz átadva, mint amikor a route-nál adtuk meg, hogy milyen adat, hová kerüljön. Például a http://localhost:xxxx/movies/details/1 a movie vezérlő detail metódusának átadja az 1-et, mint id-t. Ezt szintén átadhatjuk query stringként is (http://localhost:xxxx/movies/details?id=1).

Amennyiben található ilyen Movie, akkor az átadódik a Details nézetnek.

return View(movie);

30

Page 31: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Vizsgáljuk meg a Views\Movies\Deatils.cshtml fájl tartalmát:

@model MvcMovie.Models.Movie

@{ ViewBag.Title = "Details";}

<h2>Details</h2>

<div> <h4>Movie</h4>

<hr /> <dl class="dl-horizontal"> <dt> @Html.DisplayNameFor(model => model.Title) </dt> @*Markup omitted for clarity.*@ </dl></div><p> @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) | @Html.ActionLink("Back to List", "Index")</p>

Láthatjuk, hogy az első sorban ott van a @model kifejezés. Ezzel határozhatjuk meg, hogy milyen típusú objektumot is várunk majd. Amikor létrehoztuk a vezérlőnket, a VS automatikusan hozzáadta ezt a sort a nézetünkhöz.

@model MvcMovie.Models.Movie

A @model direktíva lehetővé teszi, hogy hozzáférjünk a vezérlő átadott Model példányhoz. Ez a példányuk erősen típusos. Például minden movie mező működik a DisplayNameFor és DisplayFor HTML helperekkel, amik egy Model típúsú objektumot várnak. A Create és Edit metódusoknak, akárcsak a nézetünknek, átadhatunk egy movie objektumot.

Vizsgáljuk meg az Index.cshtml és az Index metódusunkat a MoviesController.cs fájlban. Vizsgáljuk meg, hogyan csinálunk listát

public ActionResult Index(){    return View(db.Movies.ToList());}

Amikor megcsináltuk a movie vezérlőnket, akkor a VS automatikusan beleírta a következő sort a az Index.cshtml fájlba:

@model IEnumerable<MvcMovie.Models.Movie>

A @model direktíva lehetővé teszi a hozzáférést ahhoz a listához, amit a nézetünk a vezérlőtől kapott. Ha a következő példát megnézzük, akkor láthatjuk, hogy lényegében a foreach ciklusban az item változót csak a Model példányból szedett listaelemek segítségével deklaráljuk, mégis hozzá tudunk férni minden egyes mezőjéhez. Ezért is mondjuk, hogy erősen típusos. Az alábbi kód egyébként az Index.cshtml nézetünkben van benne:

@foreach (var item in Model) {    <tr>

31

Page 32: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

        <td>            @Html.DisplayFor(modelItem => item.Title)        </td>        <td>            @Html.DisplayFor(modelItem => item.ReleaseDate)        </td>        <td>            @Html.DisplayFor(modelItem => item.Genre)        </td>        <td>            @Html.DisplayFor(modelItem => item.Price)        </td>         <th>            @Html.DisplayFor(modelItem => item.Rating)        </th>        <td>            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |            @Html.ActionLink("Details", "Details", { id=item.ID })  |            @Html.ActionLink("Delete", "Delete", { id=item.ID })         </td>    </tr>}

Mivel a Model objektum erősen típúsos, így minden item úgymond typúskényszerítve lesz Movie típusúvá. Ez azért is fontos, mert a kódunkat elég csak fordítási időben értelmeznie a fordítónak, nem pedig futási időben, illetve teljes IntelliSense támogatást kapunk.

Munka az adatbázissalMeghatároztunk egy connection string-et. Ezt érzékeli az Entity Framework, de még nem biztos, hogy létre is hozta. Igazából ő ezt automatikusan kezeli. Mivel LocalDB-t használunk, így meg tudjuk nézni az .mdf fájlunkat. A Solution Explorer-ben az App Data mappán belül találjuk meg. Ha nem látjuk, akkor kattintsunk a lenti kép alapján a Show All Files gombra, majd a Refresh gombra.

32

Page 33: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Kattintsunk kettőt a Movies.mdf fájlra, majd megnyílik a SERVER EXPLORER. Itt a Tables mappában megtaláljuk a létrehozott Movie táblánkat. Láthatjuk, hogy az EF automatikusan generált egy ID-t, és megjelölte azt kulcsmezőnek.

Jobb gombbal kattintsunk a táblánkra, majd a Show Table Data-t válasszuk. Itt láthatjuk a beszúrt adatokat.

33

Page 34: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Jobb klikk ismét a táblára, majd Open Table Definition. Itt láthatjuk a tábla struktúráját, amit az Entity Framework legenerált nekünk:

Láthatjuk, hogy meglehetősen jól generálta nekünk a táblázat sémáját azok alapján az adatok alapján, amiket az osztályban megírtunk.

34

Page 35: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Ha készen vagyunk, akkor zárjuk le a kapcsolatot méghozzá úgy, hogy jobb klikk a MovieDBContext-re, majd Close Connection. Ha nem zárjuk le, akkor hibát kaphatunk következőleg!

7. Az Edit metódus és az Edit nézetEbben a részen megvizsgáljuk a generált Edit metódust és a hozzá tartozó nézetet. De előtte nézzük meg, hogyan is lehet stílusosabban megjeleníteni a dátumunkat. Nyissuk meg a Models\Movie.cs fált, és a kiemelt szöveget adjuk hozzá:

using System;using System.ComponentModel.DataAnnotations;using System.Data.Entity;

namespace MvcMovie.Models{ public class Movie { public int ID { get; set; } public string Title { get; set; }

[Display(Name = "Release Date")] [DataType(DataType.Date)] [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } }

public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } }}

35

Page 36: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Régióspecifikusabb dátumot az alábbi példa alapján tudunk csinálni:

[Display(Name = "Release Date")][DataType(DataType.Date)][DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]public DateTime ReleaseDate { get; set; }

A DataAnnotation-ről majd a következő részben beszélünk kicsit jobban. A Display rész arra vonatkozik, hogy az adott mezőnek mi legyen a megjelenített neve. A DataType attribútum meghatározza az adat típusát. A DisplayFormat attribútum egy Chrome ismert bug miatt szükséges.

Futtassuk az alkalmazásunkat és navigáljunk a Movies vezérlőre. A listában keressünk egy Edit linket, majd hagyjuk rajta az egeret.

Ez lényegében egy generált Html.ActionLink a háttérben:

@Html.ActionLink("Edit", "Edit", new { id=item.ID })

A Html lényegében egy property a System.Web.Mvc.WebViewPage osztályban. Az ActionLink metódus segít dinamikus linkek generálásában a vezérlő action metódusaihoz. Az első paramétere a link szövege, ami meg fog jelenni. A második paramétere a vezérlőben lévő action metódus. A harmadik pedig egy "anonymus object", ami a route adatot generálja.

36

Page 37: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

A linkünk, mint a képen látgatjuk olyan formában generálódott le, amit a vezérlő értelmezni tud. Annak az edit metódusára fog hivatkozni az adott sorban lévő movie id-jával. Ha megvizsgáljuk az App_Start\Route.configfájlt, akkro láthatjuk, hogy ő automatikusan generálja a megfelelő Routingot, így ezzel sem kell foglalkozzunk.

public static void RegisterRoutes(RouteCollection routes){ routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );}

Használhatjuk a query stringet is. A http://localhost:xxxx/Movies/Edit?ID=3 szintén eljuttatja az adatot az Edit metódusnak az ID paramétert.

Nyissuk meg a Movie vezérlőnket. A két Edit metódust láthatjuk lentebb:

// GET: /Movies/Edit/5public ActionResult Edit(int? id){ if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Movie movie = db.Movies.Find(id); if (movie == null)

37

Page 38: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

{ return HttpNotFound(); } return View(movie);}

// POST: /Movies/Edit/5// To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598.[HttpPost][ValidateAntiForgeryToken]public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie){ if (ModelState.IsValid) { db.Entry(movie).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } return View(movie);}

Mint láthatjuk, a második Edit metódus előtt van egy HttpPost attribútum. Ez felüldefiniálja az eredi metódusunkat abban az esetben, ha POST-os kérés érkezik. Az első Edit metódus elé odaírhatnánk a HttpGet attribútumot, de nem szükséges, mert a GET az alapértelmezett, így abban az esetben az első Edit metódus fut le mindenkép. A Bind szintén egy fontos biztonsági mechanizmus ami megakadályozza, hogy a hackerek ún. "overposting"-ot tudjanak csinálni. Erről és a bind-ről kicsit bővebben itt olvashatsz. Mivel a mi programunk meglehetősen egyszerű, így minden adatot a modellhez kötünk.A ValidateAntiForgery arra szolgál, hogy meggátolja az idegen kéréseket. A párja a @Html.AntiForgeryToken az edithez tartozó nézetünkben:

@model MvcMovie.Models.Movie

@{ ViewBag.Title = "Edit";}<h2>Edit</h2>@using (Html.BeginForm()){ @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Movie</h4> <hr /> @Html.ValidationSummary(true) @Html.HiddenFor(model => model.ID)

<div class="form-group"> @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div> </div>

A @Html.AntiForgeryToken generál egy tokent, aminek később az Edit metódusban egyeznie kell. Erről a témáról és védekezési módról itt olvashatsz kicsit többet.

A GET-es Edit metódusunk kap egy ID paramétert, ami alapján előkeresi az adott filmet, és odaadja az Edit nézetünknek. Amennyiben nincs ilyen film, akkor HttpNotFound lesz a válasz. A következő kód az Edit nézetünk, amit a VS generált le:

38

Page 39: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

@model MvcMovie.Models.Movie

@{ ViewBag.Title = "Edit";}<h2>Edit</h2>@using (Html.BeginForm()){ @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Movie</h4> <hr /> @Html.ValidationSummary(true) @Html.HiddenFor(model => model.ID)

<div class="form-group"> @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.ReleaseDate, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.ReleaseDate) @Html.ValidationMessageFor(model => model.ReleaseDate) </div> </div> @*Genre and Price removed for brevity.*@ <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Save" class="btn btn-default" /> </div> </div> </div>}<div> @Html.ActionLink("Back to List", "Index")</div>@section Scripts { @Scripts.Render("~/bundles/jqueryval")}

Mint láthatjuk van egy @model MvcMovie.Models.Movie kifejezés a kód elején. Ez határozza meg, hogy a sablonunk egy Movie típusú modellt fog kapni.

A generált kódunk sok beépített helpert használ a HTML jelölők generálására. A Html.LabelFor például legenerálja az adott inputmezőkhöz a címkéket. A Html.EditorFor készít inputmezőket. A Html.ValidationMessageFor helper például egy validáló üzenetet generál.

Futtassuk az alkalmazásukat, majd navigáljuk a /Movies URL-re. Ott kattintsunk az Edit linkre. Nézzük meg az oldal forráskódját a böngészőben.

<form action="/movies/Edit/4" method="post"> <input name="__RequestVerificationToken" type="hidden" value="UxY6bkQyJCXO3Kn5AXg-6TXxOj6yVBi9tghHaQ5Lq_qwKvcojNXEEfcbn-FGh_0vuw4tS_BRk7QQQHlJp8AP4_X4orVNoQnp2cd8kXhykS01" /> <fieldset class="form-horizontal"> <legend>Movie</legend>

<input data-val="true" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />

<div class="control-group">

39

Page 40: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

<label class="control-label" for="Title">Title</label> <div class="controls"> <input class="text-box single-line" id="Title" name="Title" type="text" value="GhostBusters" /> <span class="field-validation-valid help-inline" data-valmsg-for="Title" data-valmsg-replace="true"></span> </div> </div>

<div class="control-group"> <label class="control-label" for="ReleaseDate">Release Date</label> <div class="controls"> <input class="text-box single-line" data-val="true" data-val-date="The field Release Date must be a date." data-val-required="The Release Date field is required." id="ReleaseDate" name="ReleaseDate" type="date" value="1/1/1984" /> <span class="field-validation-valid help-inline" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span> </div> </div>

<div class="control-group"> <label class="control-label" for="Genre">Genre</label> <div class="controls"> <input class="text-box single-line" id="Genre" name="Genre" type="text" value="Comedy" /> <span class="field-validation-valid help-inline" data-valmsg-for="Genre" data-valmsg-replace="true"></span> </div> </div>

<div class="control-group"> <label class="control-label" for="Price">Price</label> <div class="controls"> <input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" type="text" value="7.99" /> <span class="field-validation-valid help-inline" data-valmsg-for="Price" data-valmsg-replace="true"></span> </div> </div>

<div class="form-actions no-color"> <input type="submit" value="Save" class="btn" /> </div> </fieldset></form>

Mint láthatjuk, az <input> elemeink legenerálódtak, illetve a <formo> elemnek a /Movies/Edit metódus van beállítva (ide küldi majd el az adatokat). A második mező, mint láthatjuk, egy rejtett mező, ezt a @Html.AntiForgeryToken generálta.

POST kérés kezelése

A következő kód az Edit metódusunk POST változata:

[HttpPost][ValidateAntiForgeryToken]public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie){ if (ModelState.IsValid) { db.Entry(movie).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } return View(movie);}

40

Page 41: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

A ValidateAntiForgeryToken fogja validálni a rejtett input mezőnket.

Az ASP.NET MVC modell binder megkapja a posztolt adatokat és lekreálja belőlük a Movie objektumot. Amennyiben az adatok validak, elmenti az adatbázisba a db(MovieDBContext objektum) segítségével. A konkrét mentést a db.SaveChanges() végzi. A mentés után visszairányítjuk a felhasználót az Index oldalra.

Ha be van kapcsolva a böngészőnkben a Javascript, akkor van egy kliensoldali validálás is, így posztolás előtt jelzi, hogy a beírt adat helytelen. Viszont ha ki van kapcsolva, az adatok el lesznek küldve a szervernek, ott lesznek validálva, és visszakapjuk ugyan úgy a formunkat, csak bejelölve, hogy mely adatok hibásak. Ebben a Html.ValidationMessageFor helper segít nekünk.

Minden HttpGet metódus hasonlóan egyszerűen működik. Kapnak egy Movie objektumot (a Create esetében ez egy üres objektum) és továbbadják a hozzájuk tartozó nézetnek. A lényegi módosítást a felüldefiniált metódus fogja végezni, ami POST formában kapja az adatokat. Ez biztonsági okok miatt van így egyrészt. Kicsit bővebben itt olvashatsz.

Mivel mi általában nem angol nyelvű számítógépeket használunk, így bizonyos dolgokon állítanunk kell kicsit.

41

Page 42: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Megjegyzés: Amennyiben szeretnénk, hogy nem csak angol formátumú tört számokat tudjunk megadni, illetve nem angol formátumú dátumokat szeretnénk használni, impotálnunk kell a globalize.js fájlt és a nekünk szükséges cutures/globalize.cultures.js fájlt. Innen tölthetőek le.

1. A Tools menüben kattintsunk a Library Package Manager-re, majd a Manage NuGet Packages for Solution-re.

2. A jobb oldalon válasszuk az Online részt.

3. A Search Installed Packages résznél írjuk be, Globalize.

42

Page 43: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Kattintsunk az Install-ra. a globalize.js hozzáadódik a projectünkhöz. A Sripts/jquery.globalize/cultures/ mappa tartalmazza sok a különböző országok által használt formátumokat.

A következő kód szemlélteti, milyen módosítást kell végrehajtanunk az Edit.cshtml fájlban.

@Scripts.Render("~/bundles/jqueryval")

<script src="~/Scripts/globalize/globalize.js"></script><script src="~/Scripts/globalize/cultures/globalize.culture.@(System.Threading.Thread.CurrentThread.CurrentCulture.Name).js"></script><script> $.validator.methods.number = function (value, element) { return this.optional(element) || !isNaN(Globalize.parseFloat(value)); } $(document).ready(function () { Globalize.culture('@(System.Threading.Thread.CurrentThread.CurrentCulture.Name)'); });</script><script> jQuery.extend(jQuery.validator.methods, { range: function (value, element, param) { //Use the Globalization plugin to parse the value var val = Globalize.parseFloat(value); return this.optional(element) || ( val >= param[0] && val <= param[1]); } }); $.validator.methods.date = function (value, element) { return this.optional(element) || Globalize.parseDate(value) || Globalize.parseDate(value, "yyyy-MM-dd"); }</script>}

Ha nem szeretnénk minden Edit fájlban ezt feltüntetni, akkor a layout fájlban elég módosítanunk.

Ezen felül az alábbi módosítást kell még végrehajtanunk a web.config fájlban:

<system.web> <globalization culture ="en-US" /> <!--elements removed for clarity--> </system.web>

8. KeresésAz első lépés az, hogy át kell kicsit írnunk az Index metódusunkat a meglévő MoviesController-ben.

ublic ActionResult Index(string searchString) {               var movies = from m in db.Movies                  select m;      if (!String.IsNullOrEmpty(searchString))     {         movies = movies.Where(s => s.Title.Contains(searchString));     } 

43

Page 44: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

     return View(movies); }

Az Index metódus első sora egy LINQ lekérdezés, ami lekéri az összes movie-t. Itt definiáljuk a lekérdezést, viszont ezen a ponton még nem fut le. Amennyiben a searchString tartalmaz adatot, akkor módosítjuk lekérdezésünket:

    if (!String.IsNullOrEmpty(searchString))     {         movies = movies.Where(s => s.Title.Contains(searchString));     }

A fenti példában a s=>s.Title egy Lambda kifejezés. A Lambda kifejezéseket a LINQ-ban szokás használni, csak úgy, mint a fenti Where metódust. A LINQ lekérdezések nem futnak le a definiálásukkor, vagy a módosításukkor. Lényegében akkor futnak csak le, mielőtt az általuk definiált váltazót használjuk, vagy pl a ToList() meghívjuk. Ez a fenti példában az Index.cshtml-ben fog csak lefutni.

Módosítanunk kell az az Index nézetünket úgy, hogy egy formot adjunk a felhasználónak.

Futtassuk az alkalmazást a következő URL-el: http://localhost:xxxx/Movies/Index?searchString=ghost. Így a szűrt adatok fognak csak megjelenni.

Ezután mivel az App_Start\RouteConfig.cs fűjlban az alábbi módon van beállítva a route, kicsit módosítsuk az Index függvényt.

{controller}/{action}/{id}

Az originál Index így néz ki:

public ActionResult Index(string searchString) {               var movies = from m in db.Movies                  select m; 

44

Page 45: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

     if (!String.IsNullOrEmpty(searchString))     {         movies = movies.Where(s => s.Title.Contains(searchString));     }      return View(movies); }

A módosított Index pedig így:

public ActionResult Index(string id) {     string searchString = id;     var movies = from m in db.Movies                  select m;      if (!String.IsNullOrEmpty(searchString))     {         movies = movies.Where(s => s.Title.Contains(searchString));     }      return View(movies); }

Ezután már átadhatjuk a keresett adatot mint 1 route adat:

Mivel a felhasználótól nem várhatjuk el, hogy minden esetben írja át a linket, így kell egy felület, ahol kereshet. Ha az előbb átírtuk az Index törzsét, írjuk vissza az eredeti állapotára:

public ActionResult Index(string searchString) {                var movies = from m in db.Movies                   select m;      if (!String.IsNullOrEmpty(searchString)) 

45

Page 46: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

    {         movies = movies.Where(s => s.Title.Contains(searchString));     }      return View(movies); }

Nyissuk meg a Views\Movies\Index.cshtml fájlt. Adjuk hozzá a kiemelt részt:

@model IEnumerable<MvcMovie.Models.Movie>  @{     ViewBag.Title = "Index"; }  <h2>Index</h2>  <p>     @Html.ActionLink("Create New", "Create")           @using (Html.BeginForm()){             <p> Title: @Html.TextBox("SearchString") <br />            <input type="submit" value="Filter" /></p>         } </p>

A Html.BeginForm készít egy <form> taget. Úgy generálódik, hogy saját magának posztolja el az adatokat ha a Filter gombra kattintunk.

Nem definiáltuk HttpPost-os metódust. Nem is kell, mivel nem módosítottunk adatot, csak szűrtünk.

Adjuk hozzű a következő Index metódust a kódunkhoz. Látni fogjuk, hogy ez fog lefutni kereséskor, mivel a formunk jelenleg POST-al küldi az adatokat.

[HttpPost] public string Index(FormCollection fc, string searchString) {     return "<h3> From [HttpPost]Index: " + searchString + "</h3>"; }

Miért is probléma ez? Lényegében az URL-ben nem tárolunk információt a keresésről, így például ha valaki könyvjelzőt akar belőle, vagy valakinek elküldeni ezt a linket, akkor nem tudja megtenni, mert nem mutatja a link azt, hogy milyen adatot adunk át. Ezért csináljuk meg úgy, hogy a formunk GET-et használjon. Cseréljük le a BeginForm részt a következőre:

46

Page 47: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

@using (Html.BeginForm("Index","Movies",FormMethod.Get))

Ebben az esetben most már a keresőform posztolásakor hiába van HttpPost-os metódusunk, akkor is a GET-es fog lefutni.

Műfaj szerinti keresés

Ha hozzáadtuk az előbb az Index HttpPost-os változatát, most töröljük.

A következő lépés, hogy hozzáadjunk egy olyan funkciót, hogy a felhasználó tudjon keresni műfaj szerint. Írjuk át az Index metódust.

public ActionResult Index(string movieGenre, string searchString){ var GenreLst = new List<string>();

var GenreQry = from d in db.Movies orderby d.Genre select d.Genre;

GenreLst.AddRange(GenreQry.Distinct()); ViewBag.movieGenre = new SelectList(GenreLst);

var movies = from m in db.Movies select m;

if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); }

if (!string.IsNullOrEmpty(movieGenre))

47

Page 48: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

{ movies = movies.Where(x => x.Genre == movieGenre); }

return View(movies);}

Az Index ezen verziója kap egy extra paramétert, a movieGenre-t. A metódus első sora pedig egyl istát hoz létre a műfajokból az adatbázis alapján.

48

Page 49: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

A következő LINQ lekérdezés kinyeri az adatbázisból az összes műfajt:

var GenreQry = from d in db.Movies                    orderby d.Genre                    select d.Genre;

Az AddRange metódus a Distinct segítségével a listánkból kiszűri a duplikált elemeket. Ezután a ViewBag.MovieGenre objektum tárolja a műfajok listáját SelectList-ként, ami lényegében egy lenyíló menü a háttérben.

A következő kód megmutatja, hogyan vizsgáljuk meg a movieGenre paraméter értékét. Amennyiben nem null vagy üres, a lekérdezést limitája a megadott műfajra.

  if (!string.IsNullOrEmpty(movieGenre))   {      movies = movies.Where(x => x.Genre == movieGenre);   }

Nézet módosítása

Adjuk hozzá a Html.DropDownList helpert a nézetünkhöz az alábbi kód alapján:

@model IEnumerable<MvcMovie.Models.Movie>@{ ViewBag.Title = "Index";}<h2>Index</h2><p> @Html.ActionLink("Create New", "Create") @using (Html.BeginForm("Index", "Movies", FormMethod.Get)) { <p> Genre: @Html.DropDownList("movieGenre", "All") Title: @Html.TextBox("SearchString") <input type="submit" value="Filter" /> </p> }</p><table class="table">

A movieGenre paraméter egy kulcs, ami segít megtalálni a ViewBag-ben az adott elemet.

Ha paraméterként "All"-t írunk, akkor nem szűr, egyébként megadhatjuk, melyik legyen az alapértelmezetten kiválasztott elem:

@Html.DropDownList("movieGenre", "Comedy")

Mivel van "Comedy" típusunk a műfajok között, így leszűkíti az elemeket, viszont "All" nincs, így akkor megjelenít mindent.

49

Page 50: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Futtassuk az alkalmazásunkat, és navigáljunk a /Movies/Index linkre. Próbáljuk ki a keresést.

9. Új mező hozzáadásaEbben a részben megtanuljuk, hogyan változtathatunk néhány dolgot az adatbázisban.

Mint korábban már néztük, az Entity Framework létrehozta az adatbázisunkat a modell alapján. Állandóan figyeli, hogy szinkronban legyen az adatbázis sémája a modellel, amennyiben ez nem így lenne, hibát dob. Ez könnyíti a fejlesztést.

Code First Migration beállítása

A Solution Explorer-ben töröljük ki a Movies.mdf fájlunkat. Amennyiben nem találod, klikkelj a Show All Files ikonra.

50

Page 51: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Fordítsuk le az alkalmazásunkat. Nem kapunk hibát.

A Tools menüből válasszuk ki a Library Package Manager-t és ott a Package Manager Console-t.

A konzolba írjuk a következőt, majd nyomjunk entert:Enable-Migrations-ContextTypeName MvcMovie.Models.MovieDBContext

51

Page 52: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Az Enable-Migrations parancs legenerált egy Configuration.cs fájlt a Migrations mappában.

Nyissuk meg ezt a fájlt, majd az alábbi kód szerint módosítsuk:

protected override void Seed(MvcMovie.Models.MovieDBContext context){ context.Movies.AddOrUpdate( i => i.Title, new Movie { Title = "When Harry Met Sally", ReleaseDate = DateTime.Parse("1989-1-11"), Genre = "Romantic Comedy", Price = 7.99M },

new Movie { Title = "Ghostbusters ", ReleaseDate = DateTime.Parse("1984-3-13"), Genre = "Comedy", Price = 8.99M },

new Movie { Title = "Ghostbusters 2", ReleaseDate = DateTime.Parse("1986-2-23"), Genre = "Comedy", Price = 9.99M },

new Movie { Title = "Rio Bravo", ReleaseDate = DateTime.Parse("1959-4-15"), Genre = "Western", Price = 3.99M }

52

Page 53: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

); }

Kattintsunk jobb gombbal a Movie alatti kis piros jelölőre, majd válasszuk a Resolve-t majd a using MvcMovie.Models-t.

Hozzá kell még adnunk a következő sort:

using MvcMovie.Models;

A Code First Migration meghívja a Seed metódust minden migrációnál (az update-database esetén a konzolban), ez frissíti a sorokat ha már beszúrásra kerültek, vagy ha még nincsenek bent, akkor beszúrja őket.

Az alábbi kódban az AddOrUpdate függ egy ilyen utasítástól, amit fent említettük:

context.Movies.AddOrUpdate(i => i.Title, new Movie { Title = "When Harry Met Sally", ReleaseDate = DateTime.Parse("1989-1-11"), Genre = "Romantic Comedy", Rating = "PG", Price = 7.99M }

53

Page 54: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Az AddOrUpdate metódusnak átadott első paraméter meghatározza az ellenőrzése használatos property-t. Ez jelen esetben a Title mivel az csak egyedi lehet.

context.Movies.AddOrUpdate(i => i.Title,

Amennyiben manuálisan adunk meg saját duplikált adatot az alábbi hibaüzenet fogad majd:

 Sequence contains more than one element

Nyomj Ctrl+Shift+B-t, hogy lefordítsd a projectet. Ez fontos, mert a következő lépés nem fog jól működni.

A következő lépés a DbMigration osztály létrehozása az inicializáló migrációhoz. Ez a migráció létrehoz egy új adatbázist. Ezért kellett korábban törölnünk az mdf fájlt.

A Package Manager Console-ban írjk be a következő parancsot: add-migration Initial. Ezzel létrehozzuk az inicializáló migrációt. Az Initial lényegében a fájl neve, ez tetszőleges.

Létrejött a Migrations mappában egy új fájl ({Időbélyegző}_Intial.cs). Ez a fájl tartalmazza a kódot, ami az adatbázis sémáját generálja le. Amikor frissítjük az adatbázist az alant leírt módon, lefut ez a fájl és lekreálja az adatbázis sémáját. Ezután a Seedmetódus fut le, hogy feltöltse az adatbázist a teszt adatokkal.

A Package Manager Console-ba írjuk be az alábbi parancsot: update-database.

Amennyiben hibát kapunk, előfordulhat, hogy futtattuk az alkalmazásunkat az mdf fájl törlése után. Ez esetben töröljük ki a fájlt ismét, majd futtassuk az update-database parancsot. Ha még mindig hibát kapunk, töröljük a Migrations mappát, majd ismételjük meg a fent leírtakat az mdf fájl törlése óta.

Futtassuk az alkalmazásunkat, majd navigáljunk a /Movies-ra. A Seedáltal beszúrt adatok listázva lesznek.

54

Page 55: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Rating mező hozzáadása a Movie modellhez

Adjunk hozzá egy Rating mezőt a már létező Movie modellünkhöz. Nyissuk meg a Models\Movie.cs fájlt, és adjuk hozzá a következő részt a kódhoz.

public string Rating { get; set; }

A teljes Movie osztályunk most így néz ki:

public class Movie{ public int ID { get; set; } public string Title { get; set; }

[Display(Name = "Release Date")] [DataType(DataType.Date)] [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } public string Rating { get; set; }}

Fordítsuk le az alkalmazásunkat (ne futassuk).55

Page 56: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Mivel új mezőt adtunk a Movie osztályhoz, így frisstenünk kell a binding listát. Keressük meg a bind attribútumot a Create és az Edit metódusoknál:

[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")]

Ezen felül a nézetet is frissítenünk kell, hogy megjelenítse az új mezőt.

Nyissuk meg a \Views\Movies\Indey.cshtml fájlt, és módosítsuk az alábbi kód szerint:

@model IEnumerable<MvcMovie.Models.Movie>@{ ViewBag.Title = "Index";}<h2>Index</h2><p> @Html.ActionLink("Create New", "Create") @using (Html.BeginForm("Index", "Movies", FormMethod.Get)) { <p> Genre: @Html.DropDownList("movieGenre", "All") Title: @Html.TextBox("SearchString") <input type="submit" value="Filter" /> </p> }</p><table class="table"> <tr> <th> @Html.DisplayNameFor(model => model.Title) </th> <th> @Html.DisplayNameFor(model => model.ReleaseDate) </th> <th> @Html.DisplayNameFor(model => model.Genre) </th> <th> @Html.DisplayNameFor(model => model.Price) </th> <th> @Html.DisplayNameFor(model => model.Rating) </th>

<th></th> </tr>

@foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Title) </td> <td> @Html.DisplayFor(modelItem => item.ReleaseDate) </td> <td> @Html.DisplayFor(modelItem => item.Genre) </td> <td> @Html.DisplayFor(modelItem => item.Price) </td> <td> @Html.DisplayFor(modelItem => item.Rating) </td>

<td> @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |

56

Page 57: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

@Html.ActionLink("Details", "Details", new { id=item.ID }) | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) </td> </tr>}

</table>

Nyissuk meg a \Views\Movies\Create.cshtml fájlt, és módosítsuk az alábbi szerint:

<div class="form-group"> @Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price) </div> </div>

<div class="form-group"> @Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating) </div> </div>

<div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" /> </div> </div> </div>}

<div> @Html.ActionLink("Back to List", "Index")</div>

@section Scripts { @Scripts.Render("~/bundles/jqueryval")}

Futtassuk az alkalmazásunkat, majd navigáljunk a /Movies URL-re. Ekkor a következő hibaüzenetet kapjuk:

57

Page 58: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Azért kaptuk ezt a hibát, mert a Movie modell más, mint a Movie tábla az adatbázisban.

Erre van pár megoldás:

1. Az Entity Framework autómatikusan képes kidobni és újrakreálni az adatbázist, ami a fejlesztés korai szakaszában kényelmes, viszont később, mikor már éles adatok is lehetnek az adatbázisban nem alkalmazható!

2. Módosítjuk a sémát manuálisan vagy egy ere elkészített szkript segítségével.3. Használjuk a Code First Migration-t.

Mi a Code First Migration-t fogjuk használni.

Frissítsük a Seed metódust az alábbi kód szerint:

new Movie { Title = "When Harry Met Sally", ReleaseDate = DateTime.Parse("1989-1-11"), Genre = "Romantic Comedy", Rating = "PG", Price = 7.99M },

Fordítsuk le a projektet, majd a konzolban futassuk az alábbi parancsot:

add-migration Rating

Ez a parancs lényegében segít szinkronizálni az adatbázist és a modellt, ezen felül legenerálja a szükséges kódot a migrációhoz.

58

Page 59: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Miután lefutott a parancs, a VS megnyitja a generált fájlt, és láthatjuk, hogy az Up metódus segít beszúrni az új mezőt:

public partial class AddRatingMig : DbMigration{ public override void Up() { AddColumn("dbo.Movies", "Rating", c => c.String()); } public override void Down() { DropColumn("dbo.Movies", "Rating"); }}

Fordítsuk le a projektet, majd futassuk az update-database parancsot a konzolban.

Futtassuk az alkalmazásunkat, majd navigáljunk a /Movies URL-re. Most már látjuk a Rating mezőt!

59

Page 60: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Klikkeljünk a Create New linkre. Mint láthatjuk, mostmár megjelent ott is a Rating.

Kattintsunk a Create-re, majd láthatjuk, hogy megjelent az új Movie-nál az adott értékelés.

60

Page 61: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Most már a projektünk a migrációt használja, nem kell mindig eldobnunk és újrakreálnunk az adatbázisunkat.

10. ValidálásEbben a részben megtanuljuk, hogyan hozzunk létre validálási szabályokat a modellünkben.

Fontos, hogy ne isméterljük magunkat. Amikor megírunk valami kódot, akkor azt legyünk képesek levetíteni az egész programra, hogy ahol kell tudjuk használni, ne kelljen újra megírni a dolgokat. Így kisebb a hibalehetőség, és a kód is, illetve karbantarthatóbb a program.

A validálást az ASP.NET MVC biztosítja. Jó példa a fenti kis szösszenetre: a modellben kell megírnunk, és utána az egész kódunkban, ahol kell, tudjuk használni.

Szabály hozzáadása a modellhez

Nyissuk meg a Movie.cs fájlt. A System.ComponentModel.DataAnnotations nem tartalmazza a System.Web-et. A DataAnnotations alapvetően tartalmaz bizonyos validálási szabályokat, amit bármilyen osztály esetén használhatunk.

Frissítsük a Movie osztályt az alábbiak szerint. Felhasználunk pár beépített validálási szabályt is.

public class Movie{    public int ID { get; set; }

    [StringLength(60, MinimumLength = 3)]    public string Title { get; set; }

    [Display(Name = "Release Date")]    [DataType(DataType.Date)]    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]    [Required]    [StringLength(30)]    public string Genre { get; set; }

    [Range(1, 100)]    [DataType(DataType.Currency)]    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]    [StringLength(5)]    public string Rating { get; set; }}

61

Page 62: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

A StringLength szabály meghatározza a szöveg max hosszát, ezt a megszorítást az adatbázison is alkalmazza, szóval változik az adatbázis sémája. Jobb klikk a Moviestáblán, majd Server Explorer, majd Open Table Definition.

Mint a fenti képen láthatjuk, a szöveges mezők típústa NVCHAR(MAX). Használnunk kell a migrációt a séma frissítéséhez. Fordítsuk le az alkalmazást, majd nyissuk meg a Package Manager Console-t, és futassuk az alábbi parancsokat:

add-migration DataAnnotationsupdate-database

Amint lefutattuk ezt a parancsot, a VS megnyitja a létrejöt osztályt a fent megadott néven(DataAnnotations), és az Up metódus segít megváltoztatni a sémát:

public override void Up(){    AlterColumn("dbo.Movies", "Title", c => c.String(maxLength: 60));    AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false, maxLength: 30));    AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));}

A Genre mező nem lehet többé üres. A Rating mező maximum 5 karakter hosszú lehet, és a Title is maximum 60 karakter lehet, minimum pedig 3. A Price mező sémáján nem változtattunk. Valahogy így néz ki most:

62

Page 63: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Lényegében a Validaiton Property-vel adjuk meg az adott mező viselkedését. A Required és a MinimumLength attribútumok meghatározzák, hogy mindenképp kell valami értéket megadnunk, de semmi nem akadályozza meg a felhasználót. hogy csak space-eket írjon be. Erről a RegularExpression gondoskodik. Ez limitálja, hogy milyen karaktereket tudunk bevinni. A fenti kódban a Genre és a Rating csak szöveg lehet (white space, szám és speciális karakter nem megengedett). A Range attribútum meghatározza, hogy egy adott érték milyen intervallumba eshet. A StringLength attribútum meghatározza a szöveges mező maximális hosszát (opcionálisan megadható vele a minimum is). Az érték típúsok (decimal, float, int, DateTime) öröklik a Required attribútumot, így nem kell ezt külön megadni.

A CodeFirst biztosítja azt, hogy ezek a validálási attribútumok alkalmazva is legyenek, mielőtt valamit elmentenénk az adatbázisba. Például az alábbi kód hibára futna, mivel néhány értéket nem adtunk meg.

MovieDBContext db = new MovieDBContext();Movie movie = new Movie();movie.Title = "Gone with the Wind";db.Movies.Add(movie);db.SaveChanges();        // <= Will throw server side validation exception

A fenti kód a következő hibát dobja:

Validation failed for one or more entities. See  'EntityValidationErrors' property for more details.

Abban, hogy minden szabály alkalmazva legyen a .Net gondoskodik. Ha valamit elfelejtené, ő ezt jelzi, így nem maradhat ki semmi.

Validation Error UI az ASP .NET MVC-ben

Futtassuk az alkalmazásunkat, és navigáljuk a /Movies linkre.

Katt a Create New-ra, majd adjunk hozzá egy új Movie-t. Töltsük ki a mezőket invalid adatokkal. Mint láthatjuk, a jQuery klies oldali validációja jelzi is a hibát:

63

Page 64: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

Láthatjuk, hogy új jelez, hogy az adott input mezőnek a szegélye piros lesz, majd alájuk be is írja a megadott hibaüzenetet. Az ellenőrzés mind kliens oldalon, mint szerveroldalon is végbemegy, mivel akkor is validálni kell, ha esetleg a javascript ki lenne kapcsolva.

A valódi segítség viszont az, hogy nem kell ehhez egy sort sem módosítanunk a kódban. Ezt megteszi nekünk a VS illetve ezeket a szabályokat használja mind a New mind az Edit résznél.

Az adatok csak azután lesznek elküldve a szerver felé, ha a kliens oldali validálás rendben lefutott.

Hogyan is néz ki a validálás a Create View és a Create action metódusban?

Mint láthattuk, nem kell semmit módosítanunk a vezérlőben és nézetben a validáláshoz. Ezt láthatjuk a következő kódban is, ami generálása óta nem változott:

public ActionResult Create(){    return View();}// POST: /Movies/Create// To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598.

64

Page 65: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

[HttpPost][ValidateAntiForgeryToken]public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")] Movie movie){    if (ModelState.IsValid)    {        db.Movies.Add(movie);        db.SaveChanges();        return RedirectToAction("Index");    }    return View(movie);}

Az első metódust feldogozza a GET kérést, majd am ásodik pedig a POST kérést. MInt láthatjuk, a második meghívja a ModelState.IsValidmetódust. Ez megvizsgálj a kapott értékeket, amik ha helyesek, akkor bekerülnek az adatbázisba, ellenben újra legenerálódik a formunk. Alapesetben nem is jut el ideáig, ha hiba van, csakis abban az esetben, ha le vannak tiltva a szkriptek.

Ha mégis, akkor a lenti Crate.cshtml újra megjeleníti a formot, csak most meg is jelöli a hibás mezőket:

@model MvcMovie.Models.Movie@{    ViewBag.Title = "Create";}<h2>Create</h2>@using (Html.BeginForm()) {    @Html.AntiForgeryToken()        <div class="form-horizontal">        <h4>Movie</h4>        <hr />        @Html.ValidationSummary(true)        <div class="form-group">            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })            <div class="col-md-10">                @Html.EditorFor(model => model.Title)                @Html.ValidationMessageFor(model => model.Title)            </div>        </div>        @*Fields removed for brevity.*@        

        <div class="form-group">            <div class="col-md-offset-2 col-md-10">                <input type="submit" value="Create" class="btn btn-default" />            </div>        </div>    </div>}<div>    @Html.ActionLink("Back to List", "Index")</div>@section Scripts {    @Scripts.Render("~/bundles/jqueryval")}

Segítségképpen a Html.EditorFor és a Html.ValidaionMessageFor-t használja. Mind a kettő a modell objektummal dolgozik együtt, így tudják megjeleníteni a hibás input mezőket.

Mivel a szabályokat a Movie osztályban definiáltuk, így azt az Edit is képes használni.

65

Page 66: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

66

Page 67: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

DataType attribútum

Nyissuk meg a Movie.cs fájlunkat. A System.ComponentModel.DataAnnotations névtér biztosítja a validáláshoz szükséges attribútumokat. Ezen felül használhatjuk a DataType attribútumot is, amivel például jelen esetben a megjelenési dátum formáját definiáltuk illetve az árat.

       [DataType(DataType.Date)]         public DateTime ReleaseDate { get; set; }               [DataType(DataType.Currency)]         public decimal Price { get; set; }

Ez lényegében információt ad a megjelenítésnek arról, hogy mi is pontosan az adott adat típúsa. Például, ha megadjuk, hogy valaminek a formátuma Email, akkor ő autómatikusan úgy generálja le, hogy <a href="mailto:[email protected]">. Reguláris kifejezésekkel tudjuk validálni, hogy valóban helyes-e a formátuma. Ezeknek általában nincs validáló attribútuma. Sok különféle típúst biztosít, például: Date,Time,PhoneNumber, Currency, EmailAdress stb... Nem biztosít semmilyen validálást!

A DisplayFormat explicit segít meghatározni például a dátum formátumát:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]public DateTime EnrollmentDate { get; set; }

Használhatjuk magában a DisplayFormat-ot, de általában jobb együtt használni a DataType-al.

public class Movie{   public int ID { get; set; }   [Required,StringLength(60, MinimumLength = 3)]   public string Title { get; set; }   [Display(Name = "Release Date"),DataType(DataType.Date)]   public DateTime ReleaseDate { get; set; }   [Required]   public string Genre { get; set; }   [Range(1, 100),DataType(DataType.Currency)]   public decimal Price { get; set; }   [Required,StringLength(5)]   public string Rating { get; set; }}

67

Page 68: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

11. Details és Delete metódusokNyissuk meg a Movie vezérlőt, majd vizsgáljuk meg a Details metódust:

public ActionResult Details(int? id){ if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Movie movie = db.Movies.Find(id); if (movie == null) { return HttpNotFound(); } return View(movie);}

Ez is az MVC által generált metódus. Lényegében kap egy Id paramétert, ami alapján az adott Movie-t megjeleníti.

Most nézzük meg a Detele és a DeleteConfirmed metódusokat:

// GET: /Movies/Delete/5public ActionResult Delete(int? id){ if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Movie movie = db.Movies.Find(id); if (movie == null) { return HttpNotFound(); } return View(movie);}

// POST: /Movies/Delete/5[HttpPost, ActionName("Delete")][ValidateAntiForgeryToken]public ActionResult DeleteConfirmed(int id){ Movie movie = db.Movies.Find(id); db.Movies.Remove(movie); db.SaveChanges(); return RedirectToAction("Index");}

Mint láthatjuk, a HTTP GET Delete nem töröl semmit, csak visszatér egy nézettel, amiből már POST-al tudunk kérést küldeni a tényleges törlésnek. Ezt sem szabad GET-el megoldani, mert egy jelentős biztonsági rést jelent.

A DeleteConfirmed kicsit más, mivel ő más paramétert vár, illetve POST-os. Így néz ki a két metódusunk:

// GET: /Movies/Delete/5public ActionResult Delete(int? id)

//// POST: /Movies/Delete/5[HttpPost, ActionName("Delete")]public ActionResult DeleteConfirmed(int id)

68

Page 69: files.szt.ektf.hufiles.szt.ektf.hu/dl.php?file=files/Tanári+Megosztások/Bír…  · Web viewEzután válaszd ki a Visual C# kategóriát, azon belül a Web alkategóriát, majd

A lényeg annyi, hogy mivel nem pont ugyan az a paraméterezés, ezért át kell nevezzük a metódusunkat, de azt szeretnénk, hogy ezt is Delete néven szeretnénk elérni. Ezt a routing nem tudja, de tudjuk neki jelezni az ActionName attribútummal.

69