222
Web programiranje Dr. Goran Aritonović [email protected] kabinet 211

Web programiranje

  • Upload
    others

  • View
    9

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Web programiranje

Web programiranjeDr. Goran Aritonović

[email protected]

kabinet 211

Page 2: Web programiranje

Softver

• Visual Studio 2019 (16.4 ili noviji)

• Visual Studio Code

• SQL Server 2019 (2017) Express

• SQL Server Management Studio Express

2

Page 3: Web programiranje

Uvod u ASP.NET core MVC web aplikacije

Page 4: Web programiranje

ASP.NET Core

• ASP.NET Core je besplatan, open-source web framework

• ASP.NET Core je modularni framework i radi na Windows, Linux, ili Macoperativnom sistemu

• Inicijalni naziv je bio ASP.NET 5 ali mu je ime promenjeno u ASP.NET Core 1.0(Jun 2016)

• Verzija ASP.NET Core 3.1 (decembar 2019)

• Isporučuje se u vidu Nuget paketa

• Omogućava kreiranje web aplikacija i web API-ja

• Lako se integriše sa različitim klijentskim tehnologijama

• Koristi Model-View-Controller (MVC) pattern

4

Page 5: Web programiranje

MVC patern

Models

Modeli su skup klasa koje

opisuju podatke sa kojima

radimo.

Views

Pogledi su komponente

koje generišu korisnički

interfejs aplikacije

MVC patern uključuje sledeće komponente:

Controllers

Kontroleri su komponente koje

upravljaju korisničkim zahtevima,

rade sa modelom, i odabiraju pogled

kome prosleđuju podatke

5

Page 6: Web programiranje

Kreiranje ASP.NET Core web aplikacije -1

6

Page 7: Web programiranje

Kreiranje ASP.NET Core web aplikacije -2

7

Page 8: Web programiranje

Kreiranje ASP.NET Core web aplikacije -3

8

Page 9: Web programiranje

Struktura ASP.NET Core web aplikacije

9

Page 10: Web programiranje

Fajl .csproj

10

Page 11: Web programiranje

Fajl .csproj

11

<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup><TargetFramework>netcoreapp3.1</TargetFramework>

</PropertyGroup>

</Project>

Page 12: Web programiranje

Folder properties fajl launchSettings.json

12

{"iisSettings": {

"windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": {

"applicationUrl": "http://localhost:51651","sslPort": 0

}},"profiles": {

"IIS Express": {"commandName": "IISExpress","launchBrowser": true,"environmentVariables": {

"ASPNETCORE_ENVIRONMENT": "Development"}

},"WebAspCoreUvod": {

"commandName": "Project","launchBrowser": true,"applicationUrl": "http://localhost:5000","environmentVariables": {

"ASPNETCORE_ENVIRONMENT": "Development"}

}}

}

Page 13: Web programiranje

Podešavanje profila

13

Desni klik na projekat-> Properties -> Debug tab

Page 14: Web programiranje

Folder wwwroot

• Unutar podfoldera foldera wwwroot čuvaju se statički fajlovi

• Unutar klase Startup potrebno je omogućiti pristup statičkim fajlovima (konfigurisati middleware)

• Svi fajlovi unutar foldera wwwroot su javno dostupni

14

Page 15: Web programiranje

Fajl Program.cs

15

public class Program{

public static void Main(string[] args){

CreateHostBuilder(args).Build().Run();}

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args)

.ConfigureWebHostDefaults(webBuilder =>{

webBuilder.UseStartup<Startup>();});

}

Page 16: Web programiranje

Fajl Program.cs

• ASP.NET Core web aplikacija je konzolna aplikacija koj počinje izvršavanja od metode Main() u klasi Program

• Unutar Main() metode se kreira host za aplikaciju

• Default konfiguracija koristi Kestrel web server, koristi IISintegraciju i čita konfiguraciona setovanja iz appsettings.json

• Kestrel web server je podrazumevano uključen u ASP.NET Core projekt šablone

16

Page 17: Web programiranje

Kestrel web server

17

• Kestrel ne podržava deljenje iste IP adrese i porta izmešu više aplikacija• Ne može da hostuje više web sajtova na istoj IP adresi i portu

• Integracija sa IIS web serverom• Reversni proxy server (IIS) prima HTTP zahteve sa interneta i prosleđuje ih kestrelu vršeći

prethodno neku obradu• Scenario koji zahteva reverzni proxy je kada imamo više aplikacija koje dele istu IP adresu i port i

rade na istom serveru

Page 18: Web programiranje

IoC (Inversion of Control) princip dizajna koda

• IoC je princip gde se kontrola toka programa invertuje, umesto da korisnički kod kontroliše tok programa i poziva biblioteke, to radi eksterni framework

• DI (Dependency Injection) dizajn pattern implementira IoC princip koji omogućava kreiranje slabo uparenih klasa

• IoC kontejner je framework koji upravlja automatskim ubacivanjem zavisnosti u aplikaciji tako da programer ne mora voditi računa o tome

• ASP.Core ima ugrađen Dependency Injection container18

Page 19: Web programiranje

Klasa Startup

• Izvršava se kada aplikacija startuje

• Klasa Startup ima dve javne metode ConfigureServices i Configure.

• Metoda ConfigureServices se koristi za registraciju klasa od kojih zavise neke druge klase - servisa

• Servis je klasa koja će biti korišćena u drugoj klasi

• Nakon registracije servis se može koristiti bilo gde u aplikaciji

• U aplikaciji je samo potrebno da u konstruktoru zavisne klase kao parametar definišemo referencu tipa servisa. Okruženje će je automatski ubaciti.

• ConfigureServices metoda kao ulazni parametar ima IServiceCollection koji omogućava registraciju servisa u IoC kontejneru

19

Page 20: Web programiranje

Metoda ConfigureServices

Metoda AddControllersWithViews () konfiguriše servise za uobičajene karakteristike za kontrolere sapogledima

20

public void ConfigureServices(IServiceCollection services){

services.AddControllersWithViews();}

Page 21: Web programiranje

Middleware

• ASP.NET Core uvodi koncept koji se zove middleware

• Middleware je komponenta (klasa) koja se izvršva pri svakom zahtevu

• Middleware se sastoji od komponenti koje obrađuju zahtev putem protočne obrade

• Middleware se konfiguriše unutar Configure metode Startup klase

• Redosled kojim su komponente dodate u metodu Configure određuju redosled kojim se pozivaju pri obradi zahteva i obrnutom redosledu pri odgovoru. Ovaj redosled je bitan za sigurnost, perfomanse aplikacije i njenu funkcionalnost.

21

Page 22: Web programiranje

Protočna obrada zahteva

• Zahtev se prosleđuje od jedne do druge komponente

• Svaka komponenta može odlučiti da ne prosledi zahtev sledećoj komponenti što se zove kratko spojanje protočne obrade zahteva

• Kratko spajanje je često poželjno jer se izbegava nepotreban rad.

• Npr. komponenta za obradu statičkih fajlova može vratiti zahtev za statičkim fajlom i prespojiti ostatak protočne obrade.

22

Page 23: Web programiranje

Metoda Configure()

23

public void Configure(IApplicationBuilder app, IWebHostEnvironment env){

if (env.IsDevelopment()){

app.UseDeveloperExceptionPage();}else{

app.UseExceptionHandler("/Home/Error");}app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>{

endpoints.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");

});}

Page 24: Web programiranje

Metoda Configure()

• Ova metoda specificira kako aplikacija odgovara na HTTP zahteve

• Unutar ove klase se vrši protočna obrada zahteva, postoji tzv. request pipeline

• Metoda Configure ima dva ulazna parametra IApplicationBuilder i IHostingEnvironment.

• IApplicationBuilder obezbeđuje mehanizam da se konfiguriše protočna obrada

• IHostingEnvironment obezbeđuje informacije o okruženju u kome se aplikacija hostuje

• Metoda ConfigureServices() se poziva pre Configure() metode

24

Page 25: Web programiranje

Prvo pokretanje ASP.NET Core web aplikacije

25

Page 26: Web programiranje

Prvo pokretanje ASP.NET Core web aplikacije

26

Page 27: Web programiranje

ViewData i ViewBag

Page 28: Web programiranje

Klasa HomeController.cs

28

public class HomeController : Controller{

public IActionResult Index(){

return View();}

}

Page 29: Web programiranje

Index pogled klase HomeController

29

@{

ViewData["Title"] = "Home Page";

}

<div class="text-center">

<h1 class="display-4">Welcome</h1>

<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET

Core</a>.</p>

</div>

Page 30: Web programiranje

ViewData

•ViewData je rečnik koji sadrži key-value parove

•Ključevi su stringovi

•Koristi se za prosleđivanje podataka iz kontrolera ka pogledu

•Kada se pristupa podacima iz pogleda moramo izvršiti neophodno kastovanje ukoliko ne čuvamo stringove

30

Page 31: Web programiranje

Prosleđivanje podataka Index pogledu HomeController klase

Kada se unutar akcione metode ne napiše ime pogleda kome se prosleđuju podaci,već samo return View(); onda se podaci prosleđuju pogledu koji ima isto ime kao iakciona metoda.

31

public IActionResult Index()

{

ViewData["brojPonavljanja"]= 5;

ViewData["poruka"] = "Uvod u ASP.NET Core web aplikacije";

return View();

}

Page 32: Web programiranje

Pogled Index.cshtml

32

@{

ViewData["Title"] = "Home Page";

}

<div class="row">

<div class="col-md-6">

@for (int i = 0; i < (int)ViewData["brojPonavljanja"]; i++)

{

<span>Poruka: @ViewData["poruka"]</span><br />

}

</div>

</div>

Page 33: Web programiranje

Generisani html

33

Page 34: Web programiranje

ViewBag

•Koristi se za prenos podataka iz kontrolera ka pogledu•ViewBag je dinamički objekat unutar koga se

dninamički definišu svojstva•ViewBag ne zahteva kastovanje pri iščitavanju

vrednosti iz njega•Svojstvo unutar ViewBaga ne sme da se poklopi sa

ključem ViewData rečnika

34

Page 35: Web programiranje

Definisanje dinamičkih svojstava

35

public IActionResult Index(){

ViewBag.brojPonavljanja = 5;ViewBag.poruka = "Uvod u ASP.NET Core web aplikacije"; return View();

}

Page 36: Web programiranje

Pogled Index.cshtml

36

<div class="row">

<div class="col-md-6">

@for (int i = 0; i < ViewBag.brojPonavljanja; i++)

{

<span>Poruka: @ViewBag.poruka</span><br />

}

</div>

</div>

Page 37: Web programiranje

Prosleđivanje podataka metodi kontrolera

Page 38: Web programiranje

Kreiranje praznog MVC kontrolera

38

Page 39: Web programiranje

Imenovanje kontrolera

39

Page 40: Web programiranje

Klasa PozdravController

40

public class PozdravController : Controller{

public IActionResult Index(){

return View();}

}

Page 41: Web programiranje

Index metoda klase PozdravController

41

public IActionResult Index(){

ViewBag.Poruka = "Zdravo";return View();

}

Page 42: Web programiranje

Index pogled PozdravController klase

42

Desni klik unutar metode Index pa opcija Add-> View

Page 43: Web programiranje

Folder Views/Pozdrav

43

Page 44: Web programiranje

Index.cshtml klase PozdravController

44

@{

ViewData["Title"] = "Index";

}

<h1>Index</h1>

<div class="row">

<div class="col-md-6">

@ViewBag.Poruka

<br />

<a href="/Home/Index">Pocetna</a>

</div>

</div>

Page 45: Web programiranje

Poziv Index akcione metode klase PozdravController posredstvom url adrese

45

http://localhost:5000/Pozdrav/Index

http://localhost:5000/Pozdrav

Page 46: Web programiranje

Akciona metoda Pozdrav1 PozdravController klase

public IActionResult Pozdrav1(int id = 1){

ViewBag.BrojPonavljanja = id;ViewBag.Poruka = "Dobar dan";return View();

}

46

Page 47: Web programiranje

Kreiranje pogleda Pozdrav1

47

Page 48: Web programiranje

Pogled Pozdrav1.cshtml

48

@{

ViewData["Title"] = "Pozdrav1";

}

<h1>Pozdrav1</h1>

<div>

<ul>

@for (int i = 0; i < ViewBag.BrojPonavljanja; i++)

{

<li>@ViewBag.Poruka</li>

}

</ul>

</div>

Page 49: Web programiranje

Poziv Pozdrav1 akcione metode

49

Page 50: Web programiranje

Prosledjivanje parametara akcionoj metodi-1

50

http://localhost:5000/pozdrav/pozdrav1/5

Page 51: Web programiranje

Korišćenje query stringa

51

http://localhost:5000/pozdrav/pozdrav1?id=5

Page 52: Web programiranje

Pitanje 1

52

Odgovor: a

Unutar Main metode klase Program kod ASP.NET Core web aplikacije kreira se:

a. host za web aplikaciju

b. model klasa web aplikacije

c. kontroler za web aplikaciju

Page 53: Web programiranje

Pitanje 2

53

Odgovor: c

Servisi u terminologiji ASP.NET Core web aplikacija su:

a. Klase ASP.NET Core web aplikacije koje zavise od drugih klasa

b. Klase izvedene iz klase Controller

c. Klase od kojih zavise druge klase ASP.NET Core web aplikacije

Page 54: Web programiranje

Pitanje 3

54

Odgovor: a

Registracija servisa - dodavanje servisa u kolekciju servisa

aplikacije, vrši se unutar

a. Metode ConfigureServices klase Startup

b. Metode ConfigureServices klase Program

c. Metode Configure klase Startup

Page 55: Web programiranje

Pitanje 4

55

Odgovor: c

Middleware komponenta se konfiguriše unutar metode:

a. ConfigureServices klase Startup

b. Middleware klase Startup

c. Metode Configure klase Startup

Page 56: Web programiranje

Pitanje 5

56

Odgovor: a

ASP.NET Core web aplikacija ima ugrađen Dependency Injection kontejner kojia. Ubacuje objekat klase servisa u zavisnu klasub. Ubacuje pogled u ASP.NET Core web aplikacijuc. Ubacuje kontroler u ASP.NET Core web aplikaciju

Page 57: Web programiranje

Pitanje 6

57

Odgovor: c

Statički fajlovi kod ASP.NET Core web aplikacija čuvaju se unutar podfoldera sledećeg foldera:

a. Models

b. Data

c. wwwroot

Page 58: Web programiranje

Entity Framework Core

Page 59: Web programiranje

.NET Core konzolna aplikacija

59

Page 60: Web programiranje

Microsoft.EntityFrameworkCore.SqlServer

Project->Manage Nuget Packages

60

Page 61: Web programiranje

EF Core Power Tools

61

Extensios -> Manage Extensios

Page 62: Web programiranje

Baza Magacin

62

Page 63: Web programiranje

Solution Explorer

63

Page 64: Web programiranje

Desni klik na projekat pa opcija Edit

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup><OutputType>Exe</OutputType><TargetFramework>netcoreapp3.1</TargetFramework>

</PropertyGroup>

<ItemGroup><PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.2" />

</ItemGroup>

</Project>

64

Page 65: Web programiranje

Entity Framework Core

• EF Core je međuplatformska verzija Entity Frameworka

• EF Core je objektno-relacioni maper (O/RM) koji omogućava .NET programerima da rade sa bazom korišćenjem .NET objekata.

65

Page 66: Web programiranje

Strategije dizajna modela

• Database-first design, najpre se dizajnira i kreira baza podataka a zatim se generišu entiteti aplikacije

• Model-first design, najpre se dizajniraju entiteti za aplikaciju a zatim se kreira baza podataka na osnovu tih entiteta

66

Page 67: Web programiranje

Pokreni EF Core Power Tools

67

Page 68: Web programiranje

Odabir konekcije

68

Page 69: Web programiranje

Odabir tabela i kreiranje modela

69

Page 70: Web programiranje

Entitetska klasa Kategorija

70

namespace ConsoleEfCore.Models{

[Table("Kategorija")]public partial class Kategorija{

public Kategorija(){

Proizvodi = new HashSet<Proizvod>();}

[Key]public int KategorijaId { get; set; }

[Required][StringLength(70)]public string Naziv { get; set; }

[StringLength(120)]public string Opis { get; set; }

[InverseProperty(nameof(Proizvod.Kategorija))]public virtual ICollection<Proizvod> Proizvodi { get; set; }

}}

Page 71: Web programiranje

Entitetska klasa Proizvod

public partial class Proizvod{

[Key]public int ProizvodId { get; set; }

public int KategorijaId { get; set; }

[Required][StringLength(120)]public string Naziv { get; set; }

[Column(TypeName = "decimal(10, 2)")]public decimal Cena { get; set; }

[StringLength(120)]public string Opis { get; set; }

[ForeignKey(nameof(KategorijaId))][InverseProperty("Proizvodi")]public virtual Kategorija Kategorija { get; set; }

}

71

Page 72: Web programiranje

DbContext klasa namespace ConsoleEfCore.Models{public partial class MagacinContext : DbContext{

public virtual DbSet<Kategorija> Kategorije { get; set; }public virtual DbSet<Proizvod> Proizvodi { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){

if (!optionsBuilder.IsConfigured){

optionsBuilder.UseSqlServer("Data Source=.\\SqlExpress;Initial Catalog=Magacin;Integrated Security=True");}

}

}

72

Page 73: Web programiranje

DbContext klasa

• DbContext klasa je most za interakciju entitetskih klasa i baze podataka

• DbSet <TEntity> predstavlja kolekciju entitetskih objekata koji odgovaraju redovima tabele u bazi podataka

• DbContext sadrži svojstva za pristup DbSet-ovima DbSet<TEntity> za sve entitetske klase koje su mapirane u tabele baze

• DbContext klasa:– upravlja konekcijom sa odgovarajućom bazom podataka

– prati promene u objektima unutar DbSet ova

– čuva promene iz DbSetova u bazi podataka

73

Page 74: Web programiranje

Potrebne biblioteke

using System;using System.Collections.Generic;using System.Linq;using ConsoleEfCore.Models;using Microsoft.EntityFrameworkCore;

74

Page 75: Web programiranje

Čitanje podataka sa odloženim izvršavanjem upita

static void PrikaziProizvode(){

using (MagacinContext db = new MagacinContext()){

DbSet<Proizvod> listaProizvoda = db.Proizvodi;

foreach (Proizvod p in listaProizvoda){

Console.WriteLine(p.Naziv);}

}}

75

static void Main(string[] args){

PrikaziProizvode();Console.ReadLine();

}

Page 76: Web programiranje

Čitanje podataka uz materijalizaciju upita

76

static void PrikaziProizvode(){

using (MagacinContext db = new MagacinContext()){

List<Proizvod> listaProizvoda = db.Proizvodi.ToList();

foreach (Proizvod p in listaProizvoda){

Console.WriteLine(p.Naziv);}

}}

Page 77: Web programiranje

Filtriranje podatakastatic void ProizvodiIzKategorije(int id){

using (MagacinContext db = new MagacinContext()){

IQueryable<Proizvod> listaProizvoda = db.Proizvodi.Where(p => p.KategorijaId == id);

foreach (Proizvod p in listaProizvoda){

Console.WriteLine(p.Naziv + " " + p.Cena);}

}}

77

static void Main(string[] args){

ProizvodiIzKategorije(1);}

Page 78: Web programiranje

Upotreba navigacionog svojstvastatic void ProizvodiIzKategorije(int id){

using (MagacinContext db = new MagacinContext()){

IQueryable<Proizvod> listaProizvoda = db.Proizvodi.Where(p => p.KategorijaId == id);

foreach (Proizvod p in listaProizvoda){

Console.WriteLine(p.Naziv + " " + p.Cena + " " + p.Kategorija.Naziv);}

}}

78

Page 79: Web programiranje

Prikaz podataka iz povezane tabele – Include()

static void ProizvodiIzKategorije(int id){

using (MagacinContext db = new MagacinContext()){

IQueryable<Proizvod> listaProizvoda = db.Proizvodi.Include(p => p.Kategorija).Where(p => p.KategorijaId == id);

foreach (Proizvod p in listaProizvoda){

Console.WriteLine(p.Naziv + " " + p.Cena + " " + p.Kategorija.Naziv);}

}}

79

Page 80: Web programiranje

Čitanje jednog redastatic void NadjiProizvod(int id){

using (MagacinContext db = new MagacinContext()){

Proizvod p1 = db.Proizvodi.SingleOrDefault(p => p.ProizvodId == id);if (p1 != null){

Console.WriteLine(p1.Naziv + " " + p1.Cena);}else{

Console.WriteLine($"Ne postoji proizvod ciji je id = {id}");}

}}

80

Page 81: Web programiranje

Čitanje jednog reda-2static void NadjiProizvod(int id){

using (MagacinContext db = new MagacinContext()){

Proizvod p1 = db.Proizvodi.Find(id);if (p1 != null){

Console.WriteLine(p1.Naziv + " " + p1.Cena);}else{

Console.WriteLine($"Ne postoji proizvod ciji je id = {id}");}

}}

81

Page 82: Web programiranje

Primer pisanja upita

82

static void PrikaziKategorije(){

using (MagacinContext db = new MagacinContext()){

foreach (Kategorija k in db.Kategorije){

Console.WriteLine(k.KategorijaId + ": " + k.Naziv);}

}}

Page 83: Web programiranje

Prikaz podataka

static void Main(string[] args){

PrikaziKategorije();Console.WriteLine("Unesite Id kategorije:");

int id = int.Parse(Console.ReadLine());

PrikaziProizvode(id);

Console.ReadLine();}

83

Page 84: Web programiranje

Ažuriranje podataka korišćenjem EF

• DbContext objekat sadrži entity objekte koji predstavljaju podatke u odgovarajućoj bazi podataka

• Ukoliko želimo da modifikujemo podatke u bazi prvo se vrši promena sadržaja DbContext objekta a zatim se od njega traži da sačuva promene u bazi podataka

84

Page 85: Web programiranje

Atačovani i detačovani objektiDbContext

Attached Entity Detached Entity

Attached

Managed by DbContext

Tracked

Can be persisted

Detached

Managed by DbContext

Tracked

Can be persisted

85

Page 86: Web programiranje

Unos podatakastatic int UbaciKategoriju(){

using (MagacinContext db = new MagacinContext()){

Kategorija k = new Kategorija();try{

k.Naziv = "Kucna hemija";k.Opis = "Hemija za kuhinju i kupatilo";//db.Kategorije.Add(k);db.Add(k);db.SaveChanges();return k.KategorijaId;

}catch (Exception xcp){

Console.WriteLine(xcp.Message);return -1;

}

}}

86

Page 87: Web programiranje

Main() metoda

static void Main(string[] args){

int id = UbaciKategoriju();Console.WriteLine($"Ubacena kategorija ciji je Id: {id}");Console.ReadLine();

}

87

Page 88: Web programiranje

Prikaz unetog redastatic void PrikaziKategoriju(int id){

using (MagacinContext db = new MagacinContext()){

Kategorija k1 = db.Kategorije.Find(id);

if (k1 != null){

Console.WriteLine(k1.Naziv + "\n" + k1.Opis);}else{

Console.WriteLine("Ne postoji kategorija");}

}

}

88

Page 89: Web programiranje

Ažuriranje reda -1

89

static Kategorija VratiKategoriju(int id){

using (MagacinContext db = new MagacinContext()){

Kategorija k1 = db.Kategorije.Find(id);

if (k1 != null){

return k1;}else{

return null;}

}}

Page 90: Web programiranje

Ažuriranje reda -2

static int PromeniKategoriju(Kategorija k){

using (MagacinContext db = new MagacinContext()){

try{

db.Update(k);db.SaveChanges();return 0;

}catch (Exception xcp){

Console.WriteLine(xcp.Message);return -1;

}

}}

90

Page 91: Web programiranje

Main() metoda

91

static void Main(string[] args){

Kategorija k1 = VratiKategoriju(6);

k1.Naziv = "Hemija za kucu";k1.Opis = "Hemija za kuhinju, kupatilo i ostalo";int r = PromeniKategoriju(k1);

if (r == 0){

Console.WriteLine("Promenjena kategorija");}else{

Console.WriteLine("Greska pri promeni");}Console.ReadLine();

}

Page 92: Web programiranje

Brisanje reda

public static int ObrisiKategoriju(int id){

using (MagacinContext db = new MagacinContext()){

try{

Kategorija k = db.Kategorije.Find(id);db.Remove(k);db.SaveChanges();return 0;

}catch (Exception){

return -1;}

}}

92

Page 93: Web programiranje

Main() metoda

static void Main(string[] args){

int r = ObrisiKategoriju(6);

if (r == 0){

Console.WriteLine("Obrisana kategorija");}else{

Console.WriteLine("Greska pri brisanju kategorije");}Console.ReadLine();

}

93

Page 94: Web programiranje

Klasa Thread i klasa Task

• Klasa Thread koristi se za rad sa programskim nitima

• Klasa Thread nalaze se u biblioteci System.Threading

• Klasa Task predstavlja operaciju koja ne vraća vrednost izvršava se u posebnoj programskoj niti i obično se izvršava asinhrono

• Klasa Task se nalazi u biblioteci System.Threading.Tasks

• Klasa Task se koristi za izvršavanje više poslova istovremeno, svaki u posebnoj programskoj niti

94

Page 95: Web programiranje

Metode koje se izvršavaju u istoj programskoj nitistatic void Nit1(){

if (Thread.CurrentThread.Name == null){

Thread.CurrentThread.Name = "Pomocna nit";}

Console.WriteLine("".PadRight(50, '_'));Console.WriteLine("Pozdrav iz programske niti");Console.WriteLine($"Ime: {Thread.CurrentThread.Name}, Id: {Thread.CurrentThread.ManagedThreadId}");Console.WriteLine("".PadRight(50, '_'));

}static void Main(string[] args){

Thread.CurrentThread.Name = "Glavna nit";Console.WriteLine("Pocetak Main metode");Console.WriteLine($"Ime: {Thread.CurrentThread.Name}, Id: {Thread.CurrentThread.ManagedThreadId}");Nit1();

Console.WriteLine("Kraj Main metode");Console.ReadLine();

}

95

Page 96: Web programiranje

Metode koje se izvršavaju u istoj programskoj niti

96

Page 97: Web programiranje

Izvršavanje metode u posebnoj programskoj nitistatic void Main(string[] args){

Thread.CurrentThread.Name = "Glavna nit";Console.WriteLine("Pocetak Main metode");Console.WriteLine($"Ime: {Thread.CurrentThread.Name}, Id:

{Thread.CurrentThread.ManagedThreadId}");Action a = Nit1;Task t1 = new Task(a);t1.Start();Console.WriteLine("Kraj Main metode");Console.ReadLine();

}

97

Page 98: Web programiranje

Izvršavanje metode u posebnoj programskoj niti

98

Page 99: Web programiranje

Čekanje da se završi programska nit

static void Main(string[] args){

Thread.CurrentThread.Name = "Glavna nit";Console.WriteLine("Pocetak Main metode");Console.WriteLine($"Ime: {Thread.CurrentThread.Name}, Id:

{Thread.CurrentThread.ManagedThreadId}");Action a = Nit1;Task t1 = new Task(a);t1.Start();t1.Wait();Console.WriteLine("Kraj Main metode");Console.ReadLine();

}

99

Page 100: Web programiranje

Kreiranje zadatka korišćenjemlambda izrazastatic void Main(string[] args){

Console.WriteLine("Pocetak Main metode");Thread.CurrentThread.Name = "Glavna nit";Console.WriteLine($"Naziv: {Thread.CurrentThread.Name}, Id: {Thread.CurrentThread.ManagedThreadId}");Console.WriteLine($"Glavna nit, vreme: {DateTime.Now.ToLongTimeString()}");

//Task t1 = new Task(// () => Console.WriteLine($"Pomocna nit, vreme: {DateTime.Now.ToLongTimeString()}")// );

Task t1 = new Task(() =>{

Console.WriteLine("".PadRight(50,'_'));Console.WriteLine($"Id: {Thread.CurrentThread.ManagedThreadId}");Thread.Sleep(2000);Console.WriteLine($"Pomocna nit, vreme: {DateTime.Now.ToLongTimeString()}");Console.WriteLine("".PadRight(50, '_'));

});

t1.Start();

// t1.Wait();

Console.WriteLine("Kraj Main metode");Console.ReadLine();

} 100

Page 101: Web programiranje

Kreiranje zadatka korišćenjemlambda izraza

101

Page 102: Web programiranje

Vraćanje vrednosti iz zadatka

• Koristi se Task<TResult> klasa

• Koristi se Result svojstvo

102

private void button1_Click(object sender, EventArgs e){

Task<string> t1 = Task.Run(() =>{

Thread.Sleep(5000);return DateTime.Now.ToLongTimeString();

});

// UI je blokitanlabel1.Text = t1.Result;

}

Page 103: Web programiranje

Korišćenje operatora async i await

•Modifikator async označava da je metoda asinhrona

•Unutar asinhrone metode se koristi operator await koji suspenduje izvršavanje metode sve dok se zadatak ne završi

•Omogućavaju poziv asinhrone metode i čekanje rezultata bez blokiranja programske niti

103

Page 104: Web programiranje

Izvršavanje asinhrone operacije u UI programskoj nitiprivate async void button1_Click(object sender, EventArgs e){

Task<string> t1 = Task.Run(() =>{

Thread.Sleep(5000);return DateTime.Now.ToLongTimeString();

});

// linija koda se izvrsava kada je rezultat raspoloziv// UI nije blokiran

label1.Text = await t1;}

104

Page 105: Web programiranje

Kreiranje Awaitable metode

•Ako sinhrona metoda vraća void asinhroni ekvivalent vraća Task

•Ako sinhrona metoda vraća tip T, asinhroni ekvivalent vraća Task<T>

105

Page 106: Web programiranje

Asinhrona metodaprivate async Task<string> CitajAsinhrono(){

Task<string> task1 = Task.Run(() =>{

//simulacija dugotrajnog procesaThread.Sleep(3000);return DateTime.Now.ToLongTimeString();

});

return await task1;}

106

private async void button2_Click(object sender, EventArgs e){

label1.Text = await CitajAsinhrono();}

Page 107: Web programiranje

Pitanje 1

Kod Entity Frameworka Core tehnologije osnovna klasa koja se koristi kao bazna klasa za manipulaciju sa entitetskim objektima naziva se:

a. DbContext klasab. DataSet klasac. EntityContext klasa

Odogovor: a

107

Page 108: Web programiranje

Pitanje 2

Ako je MagacinContext klasa izvedena iz DbContext klase. Neka je db instanaca MagacinContext klase.Klasa MagacinContext ima svojstvo Kategorije pomoću koga se pristupa DbSet objektu tipa DbSet<Kategorija> koji se sastoji od objekata entitetske klase Kategorija.Kako se pronalazi atačovani objekat čiji id ima vrednost 1:

a. Kategorija k1 = db.Kategorije.Find(k=>k.id=1);b. Kategorija k1 = db.Kategorije.Select(1);c. Kategorija k1 = db.Kategorije.Find(1);

Odogovor: c

108

Page 109: Web programiranje

Pitanje 3

Da bi se promene unutar tipiziranog DbContext objekta označenog sa db sačuvale u bazi podatakapišemo sledeću liniju koda:a. db.Save();b. db. SaveToDatabase();c. db.SaveChanges();

Odogovor: c

109

Page 110: Web programiranje

Pitanje 4

Za kreiranje operacije koja se izvršava u posebnoj programskoj niti i koja ne vraća vrednost koristi se klasa:a. Threadb. Taskc. Task<T>

Odogovor: b

110

Page 111: Web programiranje

Pitanje 5

Za asinhronu metodu koja treba da vrati string kao povratni tip se specificira:a. Thread<string>b. Taskc. Task<string>

Odogovor: c

111

Page 112: Web programiranje

Pitanje 6

Kreirana je metoda klasa sledećeg potpisa:private async Task<string> Citaj()Na koji način pozivamo ovu metodu:a. Citaj()b. async Citaj()c. await Citaj()

Odogovor: b

112

Page 113: Web programiranje

MVC model

Page 114: Web programiranje

MVC Model

• Model predstavlja domen aplikacije

• Svrha modela je da da smisao podacima

• Model se može koristiti kao kontejner za podatke koji se prikazuju na web strani

• Najčešće se kao model podataka koristi entitetski model

114

Page 115: Web programiranje

Kreiranje ASP.NET Core web aplikacije

115

Page 116: Web programiranje

Klasa kao model – folder Models

[Table("Osoba")]public class Osoba{

public int OsobaId { get; set; }public string Ime { get; set; }public string Prezime { get; set; }public string Adresa { get; set; }

}

116

using System.ComponentModel.DataAnnotations.Schema;

Page 117: Web programiranje

Interfejs ISkladiste

namespace WebMvcModel.Models{

public interface ISkladiste{

IEnumerable<Osoba> Osobe { get; }}

}

117

Page 118: Web programiranje

Models folder

118

namespace WebMvcModel.Models

{

public class OsobaSkladiste : ISkladiste

{

public IEnumerable<Osoba> Osobe

{

get

{

Osoba os1 = new Osoba { OsobaId = 1, Ime = "Pera", Prezime = "Peric", Adresa = "Prvomajska 4" };

Osoba os2 = new Osoba { OsobaId = 2, Ime = "Mika", Prezime = "Mikic", Adresa = "Glavna 12" };

Osoba os3 = new Osoba { OsobaId = 3, Ime = "Laza", Prezime = "Lazic", Adresa = "Marije Bursac 2" };

List<Osoba> listaOsoba = new List<Osoba>()

{

os1,

os2,

os3

};

return listaOsoba;

}

}

}

}

Page 119: Web programiranje

Klasa Startup metoda ConfigureServices

119

public void ConfigureServices(IServiceCollection services){

services.AddTransient<ISkladiste, OsobaSkladiste>();services.AddControllersWithViews();

}

Kada komponenta poput kontrolera ima potrebe za implementacijom ISkladiste interfejsa ona će dobiti instancu klase OsobaSkladiste. Tranzientni servis se instancira pri svakom zahtevu za implementacijom (posredstvom konstruktora zavisne klase).

Page 120: Web programiranje

Modifikovana klasa HomeController

120

public class HomeController : Controller{

private readonly ISkladiste skladiste;

public HomeController(ISkladiste _skladiste){

skladiste = _skladiste;}public IActionResult Index(){

ViewBag.Poruka = "Lista osoba";

return View(skladiste.Osobe);}

}

Page 121: Web programiranje

Ubacivanje zavisnosti u kontroler

• Kada MVC treba da kreira novu instancu klase HomeController da bi obradio HTTP zahtev on gleda konstruktor i uviđa da on zahteva objekat koji imlementra interfejs ISkladiste

• Da bi odredio koju implentacionu klasu trebakoristi MVC konsultuje Startup klasu koja govori da treba da koristi klasu OsobaSkladiste i da se pri svakom zahtevu treba kreirati nova instanca ove klase

• MVC kreira objekat klase OsobaSkladiste i prosleđuje ga konstruktoru kontrolera

• Proces DI omogućava kontroleru da pristupi skladištu podataka kroz interfejs bez potrebe da zna koja se implementaciona klasa za to koristi

121

Page 122: Web programiranje

Kreiranje Index pogleda bazirano na modelu

122

Page 123: Web programiranje

Direktiva @model

@model IEnumerable<WebMvcModeli.Models.Osoba>

@{

ViewData["Title"] = "Index";

}

Direktiva @model omogućava da se podacima koje je kontroler prosledio pogledu korišćenjem svojstva Model. Podaci koje prosleđuje kontroler su tipizirani, u ovom slučaju objekti klase Osoba.

123

Page 124: Web programiranje

Index pogled -1<h2>Index</h2>

<table class="table table-bordered table-striped">

<thead>

<tr>

<th>

Id

</th>

<th>

Ime

</th>

<th>

Prezime

</th>

<th>

Adresa

</th>

</tr>

</thead>

124

Page 125: Web programiranje

Index pogled -2<tbody>

@foreach (Osoba os in Model) {

<tr>

<td>

@os.OsobaId

</td>

<td>

@os.Ime

</td>

<td>

@os.Prezime

</td>

<td>

@os.Adresa

</td>

</tr>

}

</tbody>

</table>

125

Page 126: Web programiranje

Prikaz Index pogleda

126

Page 127: Web programiranje

Mvc model- code first pristup

Page 128: Web programiranje

Fajl appsettings.json

{

"Logging": {

"LogLevel": {

"Default": "Information",

"Microsoft": "Warning",

"Microsoft.Hosting.Lifetime": "Information"

}

},

"AllowedHosts": "*",

"ConnectionStrings": {

"DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=OsobaDb503;Integrated Security=True;"

}

}

128

Page 129: Web programiranje

Microsoft.EntityFrameworkCore.SqlServer

129

Page 130: Web programiranje

Klasa OsobaContext

130

using Microsoft.EntityFrameworkCore;

public class OsobaContext : DbContext{

public DbSet<Osoba> Osobe { get; set; }}

Page 131: Web programiranje

Metoda AddDbContext<TContext> interfejsa IServiceCollection• Ova metoda omogućava da DbContext<TContext> objekat bude

raspoloživ za ubacivanje od strane DI kontejnera

• Omogućava da DbContextOptions<TContext> objekat bude raspoloživ za ubacivanje od strane DI kontejnera

131

Page 132: Web programiranje

Registrujemo DbContext kao servis

132

Metoda AddDbContext registruje OsobaContext klasu kao servis. Konfiguriše se kontekst da koristi Sql Server bazu podataka. Instanca klase OsobaContext se ubacuje posredstvom DI kontejnera.

using Microsoft.EntityFrameworkCore;

public void ConfigureServices(IServiceCollection services)

{

services.AddTransient<ISkladiste, OsobaSkladiste>();

services.AddDbContext<OsobaContext>(opcije =>

opcije.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))

);

services.AddControllersWithViews();

}

Page 133: Web programiranje

Klasa OsobaContext

public class OsobaContext : DbContext{

public OsobaContext(DbContextOptions<OsobaContext> opcije) : base(opcije){}

public DbSet<Osoba> Osobe { get; set; }}

133

using Microsoft.EntityFrameworkCore;

Konstruktor DbContext klase mora imati kao parametar instancu klase DbContextOptions da bi se kreirao objekat DbContext. Ovu instancu ubacuje DI kontejner. Objekat DbContextOptions sadrži opcije za kreiranje DbContext objekta.

Page 134: Web programiranje

Klasa OsobaSkladisteDb

134

namespace WebMvcModel.Models{

public class OsobaSkladisteDb : ISkladiste{

private readonly OsobaContext db;public OsobaSkladisteDb(OsobaContext _db){

db = _db;}

public IEnumerable<Osoba> Osobe => db.Osobe;}

}

Page 135: Web programiranje

Promena implementacione klase servisa

services.AddTransient<ISkladiste, OsobaSkladisteDb>();

135

Page 136: Web programiranje

Microsoft.EntityFrameworkCore.Tools

136

Page 137: Web programiranje

Code first migracije

• Omogućavaju kreiranje baze podataka na osnovu postojećih entitetskih klasa i DbContext klase

• Omogućavaju promenu baze podataka kada se promeni neka od entitetskih klasa i context klasa

• Komanda Add-Migrations Prva unutar alata Package Manager Console služi da se kreira nova migracija unutar klase Prva

• Nakon dodavanje migracije kreira se folder Migrationsunutar ASP.NET Core MVC web aplikacije

137

Page 138: Web programiranje

Dodavanje migracije

138

PM> Add-Migration Prva

Page 139: Web programiranje

Klasa Prva.cs

139

public partial class Prva : Migration

{

protected override void Up(MigrationBuilder migrationBuilder)

{

migrationBuilder.CreateTable(

name: "Osoba",

columns: table => new

{

OsobaId = table.Column<int>(nullable: false)

.Annotation("SqlServer:Identity", "1, 1"),

Ime = table.Column<string>(nullable: true),

Prezime = table.Column<string>(nullable: true),

Adresa = table.Column<string>(nullable: true)

},

constraints: table =>

{

table.PrimaryKey("PK_Osoba", x => x.OsobaId);

});

}

protected override void Down(MigrationBuilder migrationBuilder)

{

migrationBuilder.DropTable(

name: "Osoba");

}

}

Page 140: Web programiranje

Kreiranje baze na osnovu modela

140

PM> Update-Database Primena migracije na bazu

Page 141: Web programiranje

Generisana baza podataka server (localdb)\MSSQLLocalDb

141

Page 142: Web programiranje

Index strana prikazuje podatake iz baze

142

Page 143: Web programiranje

OsobaController

143

Page 144: Web programiranje

OsobaController

144

Page 145: Web programiranje

Generisani pogledi

145

Page 146: Web programiranje

Index pogled klase OsobaController

146

Page 147: Web programiranje

Unos podataka, poziv Create akcione metode

147

Page 148: Web programiranje

Model klasa sa anotacijama polja

[Table("Osoba")]public class Osoba{

public int OsobaId { get; set; }

[Required(ErrorMessage = "Morate uneti ime")][StringLength(30, ErrorMessage = "Ime je duzine do 30 karaktera")]public string Ime { get; set; }

[Required(ErrorMessage = "Morate uneti prezime")][StringLength(30, ErrorMessage = "Prezime je duzine do 30 karaktera")]public string Prezime { get; set; }

[Required(ErrorMessage = "Morate uneti adresu")][StringLength(60, ErrorMessage = "Adresa je duzine do 60 karaktera")]public string Adresa { get; set; }

}148

using System.ComponentModel.DataAnnotations;

Page 149: Web programiranje

Dodavanje nove migracije

149

PM> Add-Migration Druga

Page 150: Web programiranje

Metoda Up() migracije

150

protected override void Up(MigrationBuilder migrationBuilder)

{

migrationBuilder.AlterColumn<string>(

name: "Prezime",

table: "Osoba",

maxLength: 30,

nullable: false,

oldClrType: typeof(string),

oldType: "nvarchar(max)",

oldNullable: true);

migrationBuilder.AlterColumn<string>(

name: "Ime",

table: "Osoba",

maxLength: 30,

nullable: false,

oldClrType: typeof(string),

oldType: "nvarchar(max)",

oldNullable: true);

migrationBuilder.AlterColumn<string>(

name: "Adresa",

table: "Osoba",

maxLength: 60,

nullable: false,

oldClrType: typeof(string),

oldType: "nvarchar(max)",

oldNullable: true);

}

Page 151: Web programiranje

Primena druge migracijePM> Update-Database

151

Page 152: Web programiranje

Validacija podataka

152

Page 153: Web programiranje

Unos podataka

153

Page 154: Web programiranje

Mvc model- database first pristup

Page 155: Web programiranje

Sql Server Object explorer

155

Page 156: Web programiranje

Tabela u bazi OsobaDb503ver2

CREATE TABLE Osoba(OsobaId int IDENTITY(1,1) PRIMARY KEY NOT NULL,Ime nvarchar(50) NOT NULL,Prezime nvarchar(50) NOT NULL,Adresa nvarchar(60) NOT NULL)

156

Page 157: Web programiranje

EF Core Power Tools -1

157

Page 158: Web programiranje

EF Core Power Tools -2

158

Page 159: Web programiranje

Generisana entitetska klasa

159

public partial class Osoba

{

[Key]

public int OsobaId { get; set; }

[Required]

[StringLength(50)]

public string Ime { get; set; }

[Required]

[StringLength(50)]

public string Prezime { get; set; }

[Required]

[StringLength(60)]

public string Adresa { get; set; }

}

Page 160: Web programiranje

Generisana DbContext klasa

160

namespace WebMvcCoreBazaPrvo.Models

{

public partial class OsobaContext : DbContext

{

public OsobaContext(DbContextOptions<OsobaContext> options)

: base(options)

{

}

public virtual DbSet<Osoba> Osobe { get; set; }

}

}

Page 161: Web programiranje

Modifikovani appsettings.json

161

{

"Logging": {

"LogLevel": {

"Default": "Information",

"Microsoft": "Warning",

"Microsoft.Hosting.Lifetime": "Information"

}

},

"AllowedHosts": "*",

"ConnectionStrings": {

"DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial

Catalog=OsobaDb503ver2;Integrated Security=True;"

}

}

Page 162: Web programiranje

Metoda ConfigureServices() klase Startup

162

public void ConfigureServices(IServiceCollection services){

services.AddDbContext<OsobaContext>(opcije =>opcije.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));services.AddControllersWithViews();

}

using WebMvcCoreBazaPrvo.Models;

using Microsoft.EntityFrameworkCore;

Page 163: Web programiranje

Kreiranje OsobaController klase

163

Page 164: Web programiranje

Validacija podataka

164

Page 165: Web programiranje

Modifikovana model klasa

165

public partial class Osoba{

public int OsobaId { get; set; }

[Required(ErrorMessage = "Unesite ime")][StringLength(50, ErrorMessage = "Maksimalno 50 karaktera")]

public string Ime { get; set; }

[Required(ErrorMessage = "Unesite prezime")][StringLength(50, ErrorMessage = "Maksimalno 50 karaktera")]public string Prezime { get; set; }

[Required(ErrorMessage = "Unesite adresu")][StringLength(60, ErrorMessage = "Maksimalno 60 karaktera")]public string Adresa { get; set; }

}

Page 166: Web programiranje

Prikaz validacionih gresaka

166

Page 167: Web programiranje

Pitanje 1

Modeli podataka kod ASP.NET Core MVC web aplikacija definišu se unutar:a. foldera Modelsb. foldera wwwrootc. foldera Views

Odgovor: a

167

Page 168: Web programiranje

Pitanje 2

Unutar pogleda (cshtml) fajla podacima koje prosleđuje kontroler pristupa se:a. korišćenjem svojstva Modelb. korišćenjem ključne reči @modelc. korišćenjem klase ModelData

Odgovor: a

168

Page 169: Web programiranje

Kreiranje MVC kontrolera

Page 170: Web programiranje

Kreiranje ASP.NET Core Web aplikacije

170

Page 171: Web programiranje

Microsoft.EntityFrameworkCore.SqlServer

171

Page 172: Web programiranje

Microsoft.EntityFrameworkCore.Tools

172

Page 173: Web programiranje

Pojam kontrolera

• Kontroler je C# klasa čije su javne metode odgovorne za obradu HTTP zahteva kod ASP.NET Core MVC web aplikacija

• Ime kontrolerske klase se završava sa Controller

• Kontroler je klasa koja je obično izvedena iz bazne klase Controller

• Metoda kontrolera koja obrađuje HTTP zahtev naziva se akciona metoda ili akcija

• Svaki kontroler sadrži jednu ili više akcionih metoda

• Akciona metoda kontrolera mora biti javna, ne može biti statička, i ne može se overloadovati

• Akciona metoda može vratiti objekat bilo kog tipa

• Uobičajeno je da akciona metoda vraća objekat koji implementira IActionResult interfejs

• Akcija kontrolera prosleđuje podatke odgovarajućem pogledu

173

Page 174: Web programiranje

Rutiranje

• Rute opisuju kako se URL adrese zahteva mapiraju u akcije kontrolera

• Rute se definišu unutar middleware komponente za rutiranje

• Unutar Configure metode poziva se metoda UseEndpoints koja se koristi da se definišu rute

• Metoda MapControllerRoute se koristi za kreiranje default rute

• Ako želimo da pozovemo Details akcionu metodu OsobaController klase i da toj metodi prosledimo id parametar vrednosti 3 potrebno je uneti sledeću adresu u browseru: http://<app>/osoba/details/3

174

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

{

app.UseEndpoints(endpoints =>

{

endpoints.MapControllerRoute(

name: "default",

pattern: "{controller=Home}/{action=Index}/{id?}");

});

}

Page 175: Web programiranje

HomeController

public class HomeController : Controller

{

public IActionResult Index()

{

return View();

}

public IActionResult Privacy()

{

return View();

}

}

175

Page 176: Web programiranje

Interfejs IActionResult

• Ovim interfejsom definiše se ugovor koji predstavlja rezultat izvršavanja akcione metode

• Obično akcione metode vraćaju objekat koji implementira IActionResult interfejs

• Metoda View() bazne klase Controller vraća instancu klase ViewResult

• Metoda Json() vraća objekat klase JsonResult i koristi se kada akciona metoda treba da generiše json string

176

Page 177: Web programiranje

Model klasa Osoba i DbContext klasa OsobaContext

public class OsobaContext : DbContext{

public DbSet<Osoba> Osobe { get; set; }} 177

[Table("Osoba")]public class Osoba{

public int OsobaId { get; set; }

[Required][StringLength(30)]public string Ime { get; set; }

[Required][StringLength(30)]public string Prezime { get; set; }

[Required][StringLength(100)]public string Adresa { get; set; }

}

Page 178: Web programiranje

Definisanje konekcionog stringa u appsettings.json fajlu

{"Logging": {

"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"

}},"AllowedHosts": "*","ConnectionStrings": {

"DefaultConnection": "Data Source=.\\SqlExpress;Initial Catalog=OsobaDb1203;Integrated Security=true"}

}

178

Page 179: Web programiranje

Registrujemo DbContext kao servis

179

public void ConfigureServices(IServiceCollection services){

services.AddDbContext<OsobaContext>(opcije =>opcije.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddControllersWithViews();}

using WebMvcKontroler.Models;using Microsoft.EntityFrameworkCore;

Page 180: Web programiranje

Promenimo DbContext klasu

public class OsobaContext : DbContext

{

public OsobaContext(DbContextOptions<OsobaContext> opcije) : base(opcije)

{

}

public DbSet<Osoba> Osobe { get; set; }

}

using Microsoft.EntityFrameworkCore;

180

Page 181: Web programiranje

Kreiranje baze podataka primenom migracija

PM> Add-Migration Prva

PM> Update-Database

181

Page 182: Web programiranje

Kreirana baza podataka

182

Page 183: Web programiranje

Kreiranje kontrolera

183

Page 184: Web programiranje

Klasa OsobaController

public class OsobaController : Controller{

private readonly OsobaContext _context;

public OsobaController(OsobaContext context){

_context = context;}

}

184

Page 185: Web programiranje

Akcija Index asinhrona verzija

using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc;

using WebMvcKontroler.Models;using Microsoft.EntityFrameworkCore;

185

public async Task<IActionResult> Index(){

return View(await _context.Osobe.ToListAsync());}

Page 186: Web programiranje

Poziv Index akcije kontrolera Osoba

186

Page 187: Web programiranje

Akciona metoda Details// GET: Osoba/Details/5

public async Task<IActionResult> Details(int? id)

{

if (id == null)

{

return NotFound();

}

var osoba = await _context.Osobe

.FirstOrDefaultAsync(m => m.OsobaId == id);

if (osoba == null)

{

return NotFound();

}

return View(osoba);

}187

Page 188: Web programiranje

Poziv Details akcije kontrolera Osoba

188

Page 189: Web programiranje

Dodavanje middleware komponente za obradu odgovara sa kodnim statusom od 400 do 599

189

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

{

...

app.UseStatusCodePages();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

...

}

Page 190: Web programiranje

Loš poziv Details akcione metode

190

Page 191: Web programiranje

GET i POST akciona metoda Create

// GET: Osoba/Createpublic IActionResult Create(){

return View();}

[HttpPost][ValidateAntiForgeryToken]public async Task<IActionResult> Create([Bind("OsobaId,Ime,Prezime,Adresa")] Osoba osoba){

if (ModelState.IsValid){

_context.Add(osoba);await _context.SaveChangesAsync();return RedirectToAction(nameof(Index));

}return View(osoba);

}

191

Page 192: Web programiranje

Model binding

• Model binding je process kreiranja .NET objekata korišćenjem podataka iz HTTP zahteva

• Kreirani objekti se prosleđuju akcionim metodama kontrolera

• Model binder je komponenta MVC aplikacije koja obezbeđuje podatke za akcione metode iz različitih delova HTTP zahteva

• Model binder koristi tri izvora podataka da bi mapirao HTTP zahteve u podatke neophodne akcionim metodama• vrednosti polja forme

• vrednosti parametara iz rute

• vrednosti parametara iz query stringova

192

Page 193: Web programiranje

Svojstva i atributske klase koje koristi metoda Create• ValidateAntiForgeryToken predstavlja atributsku klasu koja sprečava

falsifikovanje zahteva

• ModelState je property kontrolera i sadrži kolekciju (name,value) parova koju su prosleđeni u POST zahtevu do servera, takođe sadrži i kolekciju grešaka za svaku vrednost koja je poslate do servera

• ModelState.IsValid ukazuje da su greške u modelu dodate u ModelState

• Pomoću atributske klase Bind se specificiraraju koja svojstva model klase se koriste u kreiranju .NET objekata od strane model bindera

• Metoda RedirectToAction poziva akciju kontrolera koja se specificira kao string parameter metode

• Ključna reč nameof se koristi da se dobije ime promenljive, tipa ili metode

193

Page 194: Web programiranje

Poziv akcione metode Create kontrolera Osoba

194

Page 195: Web programiranje

Edit GET metoda

public async Task<IActionResult> Edit(int? id){

if (id == null){

return NotFound();}

var osoba = await _context.Osobe.FindAsync(id);if (osoba == null){

return NotFound();}return View(osoba);

}

195

Page 196: Web programiranje

Edit POST metoda

196

private bool OsobaExists(int id){

return _context.Osobe.Any(e => e.OsobaId == id);}

[HttpPost][ValidateAntiForgeryToken]public async Task<IActionResult> Edit(int id, [Bind("OsobaId,Ime,Prezime,Adresa")] Osoba osoba){

if (id != osoba.OsobaId){

return NotFound();}

if (ModelState.IsValid){

try{

_context.Update(osoba);await _context.SaveChangesAsync();

}catch (DbUpdateConcurrencyException){

if (!OsobaExists(osoba.OsobaId)){

return NotFound();}else{

throw;}

}return RedirectToAction(nameof(Index));

}return View(osoba);

}

Page 197: Web programiranje

Poziv Edit GET metode kontrolera Osoba

197

Page 198: Web programiranje

Delete GET metoda

public async Task<IActionResult> Delete(int? id){

if (id == null){

return NotFound();}

var osoba = await _context.Osobe.FirstOrDefaultAsync(m => m.OsobaId == id);

if (osoba == null){

return NotFound();}

return View(osoba);}

198

Page 199: Web programiranje

Delete Post metoda

[HttpPost, ActionName("Delete")][ValidateAntiForgeryToken]public async Task<IActionResult> DeleteConfirmed(int id){

var osoba = await _context.Osobe.FindAsync(id);_context.Osobe.Remove(osoba);await _context.SaveChangesAsync();return RedirectToAction(nameof(Index));

}

ActionName klasa ukazuje da se radi o akciji Delete

199

Page 200: Web programiranje

Poziv akcije Delete kontrolera Osoba

200

Page 201: Web programiranje

Primer filtriranja podataka

201

Page 202: Web programiranje

EF Core Power Tools

202

Page 203: Web programiranje

EF Core Power Tools

203

Page 204: Web programiranje

Model klasa Kategorija

[Table("Kategorija")]

public partial class Kategorija

{

public Kategorija()

{

Proizvodi = new HashSet<Proizvod>();

}

public int KategorijaId { get; set; }

[Required]

[StringLength(70)]

public string Naziv { get; set; }

[StringLength(120)]

public string Opis { get; set; }

public virtual ICollection<Proizvod> Proizvodi { get; set; }

}204

Page 205: Web programiranje

Model klasa Proizvod

public partial class Proizvod

{

public int ProizvodId { get; set; }

public int KategorijaId { get; set; }

[Required]

[StringLength(120)]

public string Naziv { get; set; }

[Column(TypeName = "decimal(10, 2)")]

public decimal Cena { get; set; }

[StringLength(120)]

public string Opis { get; set; }

public virtual Kategorija Kategorija { get; set; }

}

205

Page 206: Web programiranje

DbContext klasa

public partial class MagacinContext : DbContext

{

public MagacinContext(DbContextOptions<MagacinContext> opcije)

: base(opcije)

{

}

public virtual DbSet<Kategorija> Kategorije { get; set; }

public virtual DbSet<Proizvod> Proizvodi { get; set; }

}

206

Page 207: Web programiranje

appsettings.json

{"Logging": {

"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"

}},"AllowedHosts": "*","ConnectionStrings": {

"DefaultConnection": "Data Source=.\\SqlExpress;Initial Catalog=Magacin;Integrated Security=true"}

}

207

Page 208: Web programiranje

DbContext kao servis

public void ConfigureServices(IServiceCollection services)

{

services.AddDbContext<MagacinContext>(opcije =>

opcije.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddControllersWithViews();

}

208

Page 209: Web programiranje

Klasa HomeController

private readonly MagacinContext db;

public HomeController(MagacinContext _db)

{

db = _db;

}

public IActionResult Index()

{

return View(db.Kategorije.ToList());

}

209

Page 210: Web programiranje

Metoda za filtriranje

public IActionResult VratiProizvode(int id=0)

{

IQueryable<Proizvod> listaProizvoda = db.Proizvodi;

if (id != 0)

{

Kategorija k1 = db.Kategorije.Find(id);

if (k1 != null)

{

ViewBag.Kategorija = k1.Naziv;

listaProizvoda = listaProizvoda.Where(p => p.KategorijaId == id);

}

else

{

ViewBag.Kategorija = "";

return View();

}

}

else

{

ViewBag.Kategorija = "Svi proizvodi";

}

return View(listaProizvoda);

}

210

Page 211: Web programiranje

Index pogled

211

Page 212: Web programiranje

VratiProizvode

212

Page 213: Web programiranje

@model IEnumerable<WebCoreFiltriranje1.Models.Kategorija>

@{

ViewData["Title"] = "Index";

}

<h1>Index</h1>

<table class="table">

<thead>

<tr>

<th>

Naziv

</th>

<th>

Opis

</th>

<th></th>

</tr>

</thead>

<tbody>

@foreach (Kategorija k in Model) {

<tr>

<td>

@k.Naziv

</td>

<td>

@k.Opis

</td>

<td>

<a href="@($"/Home/VratiProizvode/{k.KategorijaId}")">Vidi proizvode</a>

</td>

</tr>

}

</tbody>

</table>

Index.cshtml

213

Page 214: Web programiranje

@model IEnumerable<WebCoreFiltriranje1.Models.Proizvod>

@{

ViewData["Title"] = "VratiProizvode";

}

<div class="jumbotron">

<h1>

@ViewBag.Kategorija

</h1>

</div>

@if (ViewBag.Kategorija != "")

{

<table class="table">

<thead>

<tr>

<th>

Naziv

</th>

<th>

Cena

</th>

<th>

Opis

</th>

<th>

Kategorija

</th>

<th></th>

</tr>

</thead>

VratiProizvode.cshtml

214

Page 215: Web programiranje

<tbody>

@foreach (Proizvod p in Model)

{

<tr>

<td>

@p.Naziv

</td>

<td>

@p.Cena

</td>

<td>

@p.Opis

</td>

<td>

@p.Kategorija.Naziv

</td>

</tr>

}

</tbody>

</table>

}

else

{

<p>Ne postoji kategorija</p>

}

<br>

<a href="/Home/Index">Prikazi kategorije</a>

215

Page 216: Web programiranje

Pitanje 1

MVC web aplikacija se izvršava na adresi http://localhost:5000. Ako želimo da pozovemo Details akcionu metodu OsobaController klase i da toj metodi prosledimo vrednost 3 kao ulazni parametar ove metode, potrebno je uneti sledeću adresu u browseru:a. http://localhost:5000/Osoba/Details/3b. http://localhost:5000/OsobaController/details/3c. http://localhost:5000/Osoba/details/?=3

Odgovor: a

216

Page 217: Web programiranje

Pitanje 2

Komponenta ASP.NET MVC web aplikacije koja je odgovorna za obradu zahteva naziva se:a. modelb. pogledc. kontroler

Odgovor: c

217

Page 218: Web programiranje

Pitanje 3

Zaokruži netačno tvrđenje. Kontrolerska klasa:a. Ima ime koje se završava sa rečju Controllerb. Može biti izvedena iz klase Controllerc. Mora biti opisana atributskom klasom [Authorize]

Odgovor: c

218

Page 219: Web programiranje

Pitanje 4

Interfejs pomoću koga se specificira povratni tip akcione metode kontrolera je :a. IDbContextb. IActionResultc. IJson

Odgovor: b

219

Page 220: Web programiranje

Pitanje 5

Ako akciona metoda kontrolera nije opisana atributskom klasom onda se ona može pozvati:a. GET zahtevb. POST zahtevc. I GET i POST zahtevom

Odgovor: c

220

Page 221: Web programiranje

Pitanje 6

221

Odgovor: a

Proces kreiranja .NET objekata na osnovu parametara HTTP zahteva u metodama

kontrolera naziva se

a. Model binding

b. Controller binding

c. Pogled binding

Page 222: Web programiranje

Pitanje 7

222

Odgovor: b

Validnost podataka koji su prosleđeni do akcione metode

kontrolera proverava se korišćenjem izraza

a. ModeBinding.IsValid

b. ModelState.IsValid

c. Model.IsValid