ASP.NET CORE MVC Model réteg bevezetése Model Binding Repository tervezési minta Dependency Injection Transient és Singleton Custom Binding AutoMapper

Hasonló dokumentumok
WEBFEJLESZTÉS 2. ADATBÁZIS-KEZELÉS, OSZTÁLYOK

Objektumorientált programozás C# nyelven

A gyakorlat során az alábbi ábrán látható négy entitáshoz kapcsolódó adatbevitelt fogjuk megoldani.

OOP: Java 11.Gy: Enumok, beágyazott osztályok. 13/1 B ITv: MAN

Objektumorientált Programozás VI.

OOP #14 (referencia-elv)

3. Osztályok II. Programozás II

MVC. Model View Controller

Szoftvertechnolo gia 7. gyakorlat

Objektum Orientált Programozás IV.

Szoftvertechnolo gia gyakorlat

Objektumorientált Programozás IV.

Programozás I. Gyakorlás egydimenziós tömbökkel Többdimenziós tömbök Gyakorló feladatok V 1.0 ÓE-NIK-AII,

Vizuális és eseményvezérelt programozás , II. félév BMF NIK

Webes alkalmazások fejlesztése 8. előadás. Webszolgáltatások megvalósítása (ASP.NET WebAPI)

JavaServer Pages (JSP) (folytatás)

Objektumorientált programozás C# nyelven

Programozási nyelvek II. JAVA

Java. Perzisztencia. ANTAL Margit. Java Persistence API. Object Relational Mapping. Perzisztencia. Entity components. ANTAL Margit.

Szerializáció. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) Szerializáció / 22

Webes alkalmazások fejlesztése 2. előadás. Webfejlesztés MVC architektúrában (ASP.NET) Webfejlesztés MVC architektúrában Fejlesztés ASP.

PHP alapjai, bevezetés. Vincze Dávid Miskolci Egyetem, IIT

Függőség injekció Konstantinusz Kft 2010

Vizuális, eseményvezérelt programozás XI.

Miután létrehoztuk, szeretnénk neki beszédesebb nevet adni. A név változtatásához a következőt kell tenni:

Java Programozás 11. Ea: MVC modell

Java és web programozás

Osztályok. 4. gyakorlat

Webes alkalmazások fejlesztése 4. előadás. Megjelenítés és tartalomkezelés (ASP.NET)

Számítástechnika II. BMEKOKAA Előadás. Dr. Bécsi Tamás

Öröklés és Polimorfizmus

Webes alkalmazások fejlesztése 4. előadás. Megjelenítés és tartalomkezelés (ASP.NET) Cserép Máté.

Java Server Pages - JSP. Web Technológiák. Java Server Pages - JSP. JSP lapok életciklusa

Pénzügyi algoritmusok

Sorosítás (szerializáció) és helyreállítás. 1. Bináris sorosítás és helyreállítás Szükséges névterek Attribútumok. 1.3.

ASP.NET CORE MVC. ASP.NET Core bevezetés, Hello World MVC workflow Controller réteg View réteg HTML leíró nyelv ViewModel

JUnit. JUnit használata. IDE támogatás. Parancssori használat. Teszt készítése. Teszt készítése

OOP: Java 8.Gy: Abstract osztályok, interfészek

WCF, Entity Framework, ASP.NET, WPF 1. WCF service-t (adatbázissal Entity Framework) 2. ASP.NET kliens 3. WPF kliens

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban

Adatbázis Rendszerek II. 5. PLSQL Csomagok 16/1B IT MAN

BME MOGI Gépészeti informatika 8.

C++ programozási nyelv Konstruktorok-destruktorok

Java Programozás 4. Gy: Java GUI. Tipper, MVC kalkulátor

Programozás II gyakorlat. 7. Példák a polimorfizmus alkalmazásaira

Az osztályok csomagokba vannak rendezve, minden csomag tetszőleges. Könyvtárhierarhiát fed: Pl.: java/util/scanner.java

Programozási technológia

és az instanceof operátor

Java és web programozás

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán

Grafikus keretrendszer komponensalapú webalkalmazások fejlesztéséhez

Választó lekérdezés létrehozása

Swing GUI készítése NetBeans IDE segítségével

Webes alkalmazások fejlesztése 4. előadás. Megjelenítés és tartalomkezelés (ASP.NET Core) Cserép Máté

Webshop készítése ASP.NET 3.5 ben I.

SQL jogosultság-kezelés. Privilégiumok Grant és Revoke Grant Diagrammok

Kivételkezelés, beágyazott osztályok. Nyolcadik gyakorlat

C++ programozási nyelv

Java és web programozás

A Java nyelv. Dialógus ablakok. Elek Tibor

JEE tutorial. Zsíros Levente, 2012

Objektum Orientált Programozás VII.

Objektumorientált programozás C# nyelven

Programozási nyelvek Java

Programozás I. Szöveges fájlok kezelése Felsorolástípus Objektumtömb Gyakorló feladatok

Webes alkalmazások fejlesztése 2. előadás. Webfejlesztés MVC architektúrában (ASP.NET Core) Cserép Máté

C#, OOP. Osztályok tervezése C#-ban

Programozás II. 2. gyakorlat Áttérés C-ről C++-ra

500. AA Megoldó Alfréd AA 500.

PHP. Adatbázisok gyakorlat

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1

Számítástechnika II. BMEKOKAA Előadás. Dr. Bécsi Tamás

Webes alkalmazások fejlesztése 10. előadás. Webszolgáltatások tesztelése (ASP.NET Core) Cserép Máté

.Net adatstruktúrák. Készítette: Major Péter

Programozás II. labor

JAVA PROGRAMOZÁS 2.ELŐADÁS

Objektumorientált Programozás VI.

Java és web programozás

C++ programozási nyelv

Access adatbázis elérése OLE DB-n keresztül

Entity Framework alapú adatbáziselérés 2

Memória játék. Felhasználói dokumentáció

Java VI. Miskolci Egyetem Általános Informatikai Tanszék. Utolsó módosítás: Ficsor Lajos. Java VI.: Öröklődés JAVA6 / 1

Dr. Pál László, Sapientia EMTE, Csíkszereda WEB PROGRAMOZÁS 2.ELŐADÁS. Objektumorientált programozás

Adatbázisok webalkalmazásokban

Eseményvezérelt és objektumorientált programozás

Enterprise JavaBeans. Ficsor Lajos Általános Informatikai Tanszék Miskolci Egyetem. Az Enterprise JavaBeans

GenerikusOsztály<objektumtípus> objektum = new GenerikusOsztály<objektumtípus>();

Modern unit és integrációs tesztelés

Az iskolai rendszerű képzésben az összefüggő szakmai gyakorlat időtartama. 10. évfolyam Adatbázis- és szoftverfejlesztés gyakorlat 50 óra

ELTE SAP Excellence Center Oktatóanyag 1

ZH mintapélda. Feladat. Felület

Fordított és szkript nyelvek összehasonlító elemzése. Sergyán Szabolcs

XML Webszolgáltatás alapú osztott alkalmazás fejlesztése Johanyák Zsolt Csaba 1

Készítette: Gál Tamás. A tananyag programozott változata itt érhető el: Webfejlesztés

Bevezetés a Python programozási nyelvbe

Előszó. Bevezetés. Java objektumok leképzése relációs adatbázisokra OJB-vel Viczián István Viczián István

Információs technológiák 2. Gy: CSS, JS alapok

Természetesen készíts egy csempe nevű könyvtárat és ide mentsd az index.html állományt.

Bevezető. Servlet alapgondolatok

Átírás:

ASP.NET CORE MVC Model réteg bevezetése Model Binding Repository tervezési minta Dependency Injection Transient és Singleton Custom Binding AutoMapper

Hallgatói tájékoztató A jelen bemutatóban található adatok, tudnivalók és információk a számonkérendő anyag vázlatát képezik. Ismeretük szükséges, de nem elégséges feltétele a sikeres zárthelyinek, illetve vizsgának. Sikeres zárthelyihez, illetve vizsgához a jelen bemutató tartalmán felül a kötelező irodalomként megjelölt anyag, a gyakorlatokon szóban, illetve a táblán átadott tudnivalók ismerete, valamint a gyakorlatokon megoldott példák és az otthoni feldolgozás céljából kiadott feladatok önálló megoldásának képessége is szükséges.

Model réteg Webalkalmazásunk működési magjának osztályai Egyed osztályok (autó, személy, hitel, stb.) Egy entitást írnak le Összefogják a jellemzőket és függvényeket, amelyek egy entitás sajátjai Business Logic Pl. egy kártyajáték működését foglalja magában (szabályok, keverés, stb.) Pl. egy üzleti alkalmazás különböző funkciói Megjelenítési rétegtől teljesen független logikai osztályok Mindig úgy kell megírni, hogy akár ConsoleApp-ban is működjön! Repository Elfedi az adatbázist különböző függvényekkel Business Logic fogja használni folyamatosan Erősen javasolt interfészt használni 3

Model feladata Megjelenítés során Összegyűjtjük egy modelben a megjelenítendő információkat (Controller végzi) A modelt átadjuk a View-nak Adatbevitel során A HTML form mezőinek értéke átadásra kerül a Controllernek Controller egy Modelt példányosít belőle 4

Feladat Készítsünk egy egyszerű regisztrációs felületet, ahol egy hallgatót tudunk beiratkoztatni az egyetemre! Egy hallgató adatai: Név Neptunkód Évfolyam Szak A hallgató kezeléséhez készítsünk megfelelő Model osztályt! 5

1. Model osztály elkészítése Készítsük el az alábbi mappaszerkezetet A Model osztály nevébe szokás beleírni, hogy Model public class HallgatoModel public string Nev get; set; public string Neptunkod get; set; public int Evfolyam get; set; public string Szak get; set; 6

2. Controller Osztályszintű tagként kezeljük public class HomeController : Controller List<HallgatoModel> hallgatok; public HomeController() hallgatok = new List<HallgatoModel>(); public IActionResult Index() return View(hallgatok); [HttpGet] public IActionResult Add() return View(); a listát Konstruktorban példányosítjuk a listát Az index Action átadja az összes hallgatót a View-jának Majd itt lesz hozzáadás gomb A hozzáadás gomb hatására idekerülünk, itt lesz a form, a formot ugyanide küldjük el, de POST-al [HttpPost] public IActionResult Add(HallgatoModel model) hallgatok.add(model); return RedirectToAction("Index"); POST változat, ez kapja meg a form eredményét, hozzáadja a hallgatót és visszaküld az Indexre egy View mutatás helyett. 7

3. Index View @model List<ASPKurzus02.Models.HallgatoModel> <body> <h2>hallgatók</h2> <p> <a href="/home/add">új hallgató</a> </p> <table> <tr> <th>név</th> <th>neptunkód</th> <th>évfolyam</th> <th>szak</th> </tr> @foreach (var item in Model) <tr> <td>@item.nev</td> <td>@item.neptunkod</td> <td>@item.evfolyam</td> <td>@item.szak</td> </tr> </table> </body> 8

3. Add View @model ASPKurzus02.Models.HallgatoModel <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>új Hallgató</title> </head> <body> <form method="post" action="add"> Név: <br /><input type="text" name="nev" /> <br /> Neptunkód: <br /><input type="text" name="neptunkod" /> <br /> Évfolyam: <br /><input type="text" name="evfolyam" /> <br /> Szak: <br /><input type="text" name="szak" /> <br /> <input type="submit" value="beiratkozás" /> </form> </body> </html> 9

Model Binding Hogyan kerülnek a form adatok egy objektumba?! Eddigiekben átadtuk az összes form elem értékét paraméterként Ott is megfigyeltük, hogy a típusátalakítás automatikus (int.parse()) A Model Binder mechanizmus képes a form adatokból objektumot példányosítani 10

Model Binding Működési követelmények Az osztálynak legyen paraméternélküli konstruktora Tulajdonságai írhatók és publikusak legyenek A HTML Form name attribútumai egyezzenek meg a Model osztály tulajdonság neveivel Pozitívumok Nem szükséges konstruktort írnunk rengeteg this.valami = valami jellegű sorral 11

Tesztelés Nem jelennek meg a felvitt hallgatók az Indexen Debug a Post Action-re! Láthatjuk, hogy megérkezett a model, és a Model Binder is tökéletesen beillesztette a form értékeit az egyes tulajdonságokba Probléma: A Controller minden egyes Action híváskor újrapéldányosul. Teljesen új listánk van az Index hívásakor. 12

Megoldás Repository tervezési minta Készítünk egy osztályt, ami a tárolásért felelős Ennek az osztálynak a metódusait fogjuk hívogatni a Controllerből 13

2. HallgatoRepository.cs Osztályszintű tagként public class HallgatoRepository List<HallgatoModel> hallgatok; public List<HallgatoModel> GetAll get return hallgatok; public HallgatoRepository() hallgatok = new List<HallgatoModel>(); public void AddHallgato(HallgatoModel model) hallgatok.add(model); kezeljük a listát A listát tulajdonságként visszaadjuk Később majd interfésszel Konstruktorban példányosítjuk a listát Biztosítunk metódust arra, hogy új hallgatót lehessen felvenni 14

2. Módosított Controller Osztályszintű tagként public class HomeController : Controller HallgatoRepository tarolo; public HomeController() tarolo = new HallgatoRepository(); kezeljük repót Példányosítjuk a repót public IActionResult Index() return View(tarolo.GetAll); [HttpGet] public IActionResult Add() return View(); Továbbra is fennáll a probléma, hogy a Controller újrapéldányosul, és új repónk lesz így [HttpPost] public IActionResult Add(HallgatoModel model) tarolo.addhallgato(model); return RedirectToAction("Index"); 15

Megoldás Valahol máshol példányosítjuk a repót! Startup.cs? Hogy adjuk át? Sehol nem találjuk a Controller konstruktorhívását, hogy beletegyük Dependency Injection + Singleton minta Egy függőség-beszúrás nevezetű mechanizmus példányosít nekünk egyet a repóból és automatikusan átadja a Controller konstruktorának Singleton minta: az osztályunkból egy példány létezik, és bárhol példányosítjuk le, az mindig ugyanarra a memóriában lévő objektumra mutat. 16

Megvalósítás Controller módosítása Startup.cs: ConfigureServices() kiegészítése 17

Transient vs Singleton services.addtransient<hallgatorepository, HallgatoRepository>(); Mindig új példányt ad át Hogyha az osztály egy adatbáziskapcsolatot fed el, akkor ez bőven elegendő services.addsingleton<hallgatorepository, HallgatoRepository>(); Hogyha az átadott osztály fontos, hogy megőrizze a változói, tagjai értékét, akkor ezt kell használni Tipikusan ha nincs adatbázis, hanem valamilyen adatszerkezet a tároló 18

Repository függetlenítés Repository osztály variációk Az osztályban van egy globális tömb, lista, dictionary, stb. Az osztály konstruktorában fájlt olvas, módosításkor fájlt ír Az osztály egy adatbázisba ír/olvas Az osztály API-n keresztül pl. google drive-ba dolgozik Repository függetlenítés Készítünk egy interfészt a repó funkciókkal Pl: Hozzáadás, Törlés, Módosítás, Minden lekérése, Minden törlése, stb. Az interfészt és az adott implementációt összerendeljük Új fajta tárolásra áttérve ezt az egy sort kell más implementációra cserélni 19

Nagy feladat: CRUD alkalmazás CRUD: Create, Read, Update, Delete Készítsünk nyilvántartó alkalmazást, amelyben dolgozókat tudunk menedzselni! Készítsünk egy olyan Repositoryt, amely XML fájlból tölti be a dolgozóinkat és minden módosítás után frissíti a fájlt (későbbiekben a fájlkezelést adatbázisra cseréljük) A Repository-t interfészen át használjuk, hogy cserélhető legyen 20

Probléma Az update és a delete mint akciógombok megjelennek minden dolgozó mellett GET kérés: elküldjük az adott elem hash-ét Object őstől örökölt függvény: GetHashCode() felüldefiniálható A view-ban a törlő és módosító linknél megadhatjuk közvetlenül a hash-t (ekkor id névvel érjük el a Controllerből) Vagy beparaméterezzük a GET kérés URL-ét Repositoryban adunk lehetőséget hash alapján keresni 21

Custom binding A formon a fizetés ezer forintra kerekítve jelenik meg (pl: 100 e Ft) Érdemes lenne a Modelben ténylegesen 100000-et tárolni mindenféle belső folyamatok (bérkalkuláció, stb.) miatt Egyszerű probléma, de rengeteg ilyenbe fogunk belefutni később (pl: radiobutton -> enum konverzió) A Model Bindert utasítjuk, hogy a saját konvertáló osztályunkat hívja meg és azzal végezze a konverziót Teljesen testre tudjuk szabni, hogy a form elemei hogyan kerüljenek az objektumba WPF-ben a Converter osztályok működéséhez nagyon hasonló! 22

Custom binding Data mappa -> WorkerModelBinder.cs public class WorkerModelBinder : IModelBinder public Task BindModelAsync(ModelBindingContext bindingcontext) if (bindingcontext == null) throw new ArgumentNullException(nameof(bindingContext)); var name = bindingcontext.valueprovider.getvalue("name"); var job = bindingcontext.valueprovider.getvalue("job"); var salary = bindingcontext.valueprovider.getvalue("salary"); WorkerModel model = new WorkerModel() Name = name.firstvalue, Salary = int.parse(salary.firstvalue) * 1000, Job = job.firstvalue ; bindingcontext.result = ModelBindingResult.Success(model); return Task.CompletedTask; 23

Custom binding Attribútummal jelezzük a Model osztályunkon, hogy melyik Custom Binder osztályt használja fel a konverzióra 24

Custom binding fordítottja Szimplán a View-ban visszaalakítjuk <input type="number" name="salary" value="@(model.salary/1000)" 25

Custom binder alkalmazása Olyan esetekben, amikor valami formátum probléma van az űrlapelem tartalma -> osztály között, amit manuálisan kell megoldani Példa: Megadunk egy évet text inputban Kiválasztunk egy oktatási hetet legördülő listából De a Modelben nekünk egy kezdő és egy vég DateTime kell Ezt két DateTime-ot a két mezőből kell kiszámoltatni Ezt nyilván a Model Binder magától nem tudja 26

AutoMapper Hasonló, mint a Model Binder, de mégsem Használati eset: Vannak adatok, amelyek repó-ba kellenek, view-ba nem Vannak adatok, amelyek view-ba kellenek, repó-ba nem Vannak adatok, amelyek úgy kellenek a view-ba, hogy a Modelt ki kell egészíteni valamivel (pl. aktuális idő) Megvalósítás: ViewModel készítés CarModel Repository AutoMapper CarViewModel View 27

ViewModel (eml.) 3. Repository Models Busines Logic Controller 4. Model ViewModel Car Model Person Model View Amikor a Controller adatot továbbít a View számára, tipikusan egy darab objektumot adunk át. Abban az esetben, hogyha egy Autó objektumot és a rendelkezésünkre álló egyenleget akarjuk megjeleníteni együtt, akkor nem az adott Autó Model osztályt adjuk át, hanem létrehozunk egy ViewModelt, amely egy átmeneti megjelenítési célú összetett objektum. 28

Feladat Egészítsük ki a dolgozó CRUD alkalmazást azzal, hogy a felvett dolgozónak megadjuk a felettesét is! Egy legördülő listából engedjük kiválasztani View-nak egy objektumot adunk át Ez az új dolgozónál nem probléma, mert átadjuk a meglévő dolgozókat Módosításnál? Mi kell a view-ba? A meglévő dolgozó objektum Az összes dolgozó listája Megoldás: WorkerViewModel Tartalmazza a dolgozót, meg a többieket is 29

1. AutoMapper telepítése Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution 30

2. AutoMapper használata Egyszerű bemutató példa (nem a nagyfeladat) Kutya osztály Név Életkor KutyaDetails osztály Név Életkor Feladat: Azonosító (név hossza * életkor) Írni egy automatizmust, ami bármikor Kutya osztályból KutyaDetails osztályra tér át, vagy fordítva 31

3. Modelosztályaink public class Kutya public string Nev get; set; public int Eletkor get; set; public class KutyaDetails public string Nev get; set; public int Eletkor get; set; public int Azonosito get; set; 32

4. Konverter osztály Azonos nevű propertyk: maguktól átkerülnek public class KutyaProfile : Profile public KutyaProfile() //Kutya -> KutyaDetails áttérés CreateMap<Kutya, KutyaDetails>().ForMember(dest => dest.azonosito, options => options.mapfrom( src => src.nev.length * src.eletkor )).AfterMap((kutya, kutyadetails) => //itt lehet bonyolultabb kódot írni kutyadetails.nev = kutya.nev.toupper(); ); A -> B property ForMember részben A -> B bonyolult kód AfterMap részben //KutyaDetails -> Kutya áttérés CreateMap<KutyaDetails, Kutya>().ForMember(dest => dest.eletkor, options => options.mapfrom( src => src.eletkor + 1 )); 33

5. Felhasználás Controllerben osztályszintű tag, példányosítás 34

5. Felhasználás Action-ökben felhasználás 1: jön egy KutyaDetails, átalakítjuk Kutyára 2: jön egy Kutya, átalakítjuk KutyaDetails-re 35

5. AutoMapper mindenhol Controllerünkben mindenhol elérhető a mapper Jó lenne, ha további Controllerek is tudnák használni Kivisszük a Mappert a Startup osztályba és Singletonként használjuk bárhol 36