# MVC arhitektura
Ovaj materijal dio je ishoda učenja 4 (minimum).
Atributi validacije:
- https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-8.0#built-in-attributes
## 10 MVC arhitekturu i podrška za model
- ViewModel
- Model s povezanim podacima
- Atributi označavanja
- Validacija modela i atributi validacije
- Poslužiteljska validacija modela
- Klijentska validacija modela
- Oznake validacije i sažetak validacije
### 10.1 Postavljanje vježbe
Postavljanje baze podataka: kreirajte bazu podataka `Exercise10` sa sljedećom strukturom.
```SQL
CREATE DATABASE Exercise10
GO
USE Exercise10
GO
CREATE TABLE Genre (
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](256) NOT NULL,
[Description] [nvarchar](max) NOT NULL,
PRIMARY KEY ([Id])
)
GO
SET IDENTITY_INSERT Genre ON
GO
INSERT INTO Genre (Id, [Name], [Description])
VALUES
(1, 'Rock', 'Otherwise known as ‘Rock & Roll,’ rock music has been a popular genre since the early 1950s.'),
(2, 'Jazz', 'Identifiable with blues and swing notes, Jazz has origins in European and West African culture.'),
(3, 'Electronic Dance Music', 'Typically referred to as EDM, this type of music is created by DJs who mix a range of beats and tones to create unique music.'),
(4, 'Dubstep', 'Dubstep is an electronic dance music subgenre that originated in the late 1990s’ in South London.'),
(5, 'Techno', 'Techno is yet another sub-genre of electronic dance music. This genre became popular in Germany towards the end of the 1980s and was heavily influenced by house music, funk, synthpop, and futuristic fiction.'),
(6, 'Rhythm and Blues (R&B)', 'R & B is one of the world’s top music genres combining gospel, blues, and jazz influences.'),
(7, 'Country', 'Country music is another one of the world’s top music genres. Originating in the 1920s, Country has its roots in western music and American folk.'),
(8, 'Pop', 'The term ‘Pop’ is derived from the word ‘popular.’ Therefore, Pop music is a genre that contains music generally favored throughout society.'),
(9, 'Indie Rock', 'In terms of genre, Indie Rock lies somewhere between pop music and rock and roll.'),
(10, 'Electro', 'Electro blends electronic music and hip hop to create music that is similar to disco in sound.')
GO
SET IDENTITY_INSERT Genre OFF
GO
CREATE TABLE Artist (
Id int NOT NULL IDENTITY (1, 1),
[Name] nvarchar(256) NOT NULL
CONSTRAINT PK_Artist
PRIMARY KEY (Id)
)
SET IDENTITY_INSERT Artist ON
GO
INSERT INTO Artist (Id, [Name])
VALUES
(1, 'Tina Turner'),
(2, 'Van Halen'),
(3, 'DJ Snake'),
(4, 'Louis Armstrong')
GO
SET IDENTITY_INSERT Artist OFF
GO
CREATE TABLE Song (
Id int NOT NULL IDENTITY (1, 1),
[Name] nvarchar(256) NOT NULL,
[Year] int NULL,
GenreId int NOT NULL,
ArtistId int NOT NULL,
DeletedAt datetime2(7) NULL,
CONSTRAINT PK_Song
PRIMARY KEY (Id),
CONSTRAINT FK_Song_Genre
FOREIGN KEY(GenreId)
REFERENCES dbo.Genre (Id),
CONSTRAINT FK_Song_Artist
FOREIGN KEY(ArtistId)
REFERENCES dbo.Artist (Id)
)
SET IDENTITY_INSERT Song ON
GO
INSERT INTO Song (Id, [Name], [Year], GenreId, ArtistId)
VALUES
(1, 'What''s Love Got to Do with It', 1984, 8, 1),
(2, 'The Best', 1989, 8, 1),
(3, 'Jump', 1984, 1, 2),
(4, 'Lean On', 2015, 10, 3),
(5, 'What a Wonderful World', 1967, 2, 4),
(6, 'We Have All The Time In The World', 1969, 2, 4)
GO
SET IDENTITY_INSERT Song OFF
GO
```
Sljedeće je već dovršeno kao "starter" projekta:
> Postavljanje modela i repozitorija (za detalje pogledajte prethodnu vježbu):
>
> - Instalirajte EF pakete u projekt
> - Konfigurirajte EF connection string u `appsettings.json`
> - Napravite reverse engineering baze podataka i postavite servis u `Program.cs`
>
> "Launch settings" postavke:
>
> - Postavite port na 6555
>
> Stvorite CRUD prikaze i funkcionalnost za `GenreController`
>
> - Koristite "MVC Controller with read/write actions" predložak za stvaranje `GenreController`
> - Proslijedite db kontekst kontroleru pomoću konstruktorskog DI
> - Napravite viewmodel `GenreVM` (Id, Naziv, Opis) u mapi `ViewModels`
> - Koristite `Add View`, `Razor View`, `Template: {required template}`, `Model`: `GenreVM`
> - `Index`, `Template`: `List`
> - Popravite ovaj dio Razor predloška da ispravno stvorite akcijske poveznice
> ```C#
> @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
> @Html.ActionLink("Details", "Details", new { id=item.Id }) |
> @Html.ActionLink("Delete", "Delete", new { id=item.Id })
> ```
> - U predlošku upotrijebite neki CSS stil ili Bootstrap za fino podešavanje prikaza
> - Implementirajte akciju GET
> - `Details`: `Template`: `Details`
> - Popravite ovaj dio Razor predloška da ispravno stvorite akcijske poveznice
> ```C#
> @Html.ActionLink("Edit", "Edit", new { id = Model.Id })
> ```
> - U predlošku upotrijebite neki CSS stil ili Bootstrap za fino podešavanje prikaza
> - Implementirajte GET akciju
> - `Create`: `Template`: `Create`
> - Ažurirajte `POST` akciju tako da prihvaća viewmodel parametar
> - Implementirajte GET i POST akciju
> - `Edit`: `Template`: `Edit`
> - Ažurirajte `POST` akciju tako da prihvaća viewmodel parametar
> - Implementirajte GET i POST akcije
> - `Delete`: `Template`: `Delete`
> - Ažurirajte akciju `POST` da prihvaća viewmodel parametar
> - Implementirajte GET i POST akcije
> - Ažurirajte navigaciju na stranici "layout" - u \_Layout.cshtml, dodajte vezu za navigaciju na stranicu popisa žanrova
> ```HTML
>
> ```
> Stvorite CRUD prikaze i funkcionalnosti za `ArtistController` na isti način kao `GenreController`.
### 10.2 Viewmodel: Stvorite i postavite kontroler za entitet Song iz CRUD predloška
Koristite predložak "MVC Controller with read/write actions" za stvaranje kontrolera `SongController`.
Proslijedite db kontekst kontroleru pomoću konstruktorskog DI.
Stvorite viewmodel `SongVM` u mapi `ViewModels`:
- int Id
- string Name
- int Year
- int GenreId
- int ArtistId
### 10.3 Implementirajte indeks akciju za prikaz popisa pjesama
Na akciju `Index` kontrolera `SongController` kliknite desnom tipkom miša i odaberite:
- Add View, Razor View
- Template: List
- Model: `SongVM`
Implementirajte GET akciju.
> SAVJET: možete upotrijebiti kod koji je već dostupan u `GenreController` i prilagoditi ga za rad na `SongController`.
Ažurirajte navigaciju na stranici izgleda - u \_Layout.cshtml, dodajte navigacijsku poveznicu na stranicu popisa pjesama.
### 10.4 Popravite prikaz za popis pjesama
Postoje neki problemi s prikazom:
- postoje "gole" nestilizirane poveznice
- postoji `Id` u tablici
Da biste ih popravili, pogledajte `Views > Artists > Index.cshtml`.
### 10.5 Zamijenite ID-eve (strani ključevi) povezanim vrijednostima
Imamo model s podacima koji je povezan s drugim modelom - `Song` je povezan sa `Genre` i `Artist`.
Prvo riješimo problem gdje su podaci `Genre` i `Artist` u obliku `Id` umjesto teksta.
Uključite entitete `Genre` i `Artist` u LINQ upit.
Zatim proširite viewmodel pjesme kako biste uključili stringove za `Genre` i `Artist` (GenreName, ArtistName).
```C#
var songVms = _context.Songs
.Include(x => x.Genre)
.Include(x => x.Artist)
.Select(x => new SongVM
{
Id = x.Id,
Name = x.Name,
Year = x.Year ?? 0,
ArtistId = x.ArtistId,
ArtistName = x.Artist.Name,
GenreId = x.GenreId,
GenreName = x.Genre.Name,
})
.ToList();
```
Sada možete zamijeniti `GenreId` s `GenreName` u `Song/Index.cshtml`.
Učinite isto za `Artist`.
> Napomena: to trebate učiniti na dva mjesta u prikazu - naslov (labela) i podaci.
### 10.6 Atributi labeliranja/označavanja: postavite nazive u viewmodelu
U `Index.cshtml`, sljedeća sintaksa će ispisati podatke:
```C#
@Html.DisplayFor(modelItem => item.Name)
```
Sljedeća sintaksa će ispisati labelu za podatak:
```C#
@Html.DisplayNameFor(modelItem => item.Name)
```
Prema zadanim postavkama, labela podataka je ista kao naziv svojstva podataka.
Pomoću atributa [Display] možete promijeniti labelu podataka.
```C#
public class SongVM
{
public int Id { get; set; }
[Display(Name = "Song Name")]
public string Name { get; set; }
public int Year { get; set; }
public int GenreId { get; set; }
[Display(Name = "Genre")]
public string GenreName { get; set; }
public int ArtistId { get; set; }
[Display(Name = "Artist")]
public string ArtistName { get; set; }
}
```
Promatrajte promjenu u zaglavlju tablice popisa pjesama.
### 10.7 Koristite labelu postavljenu u viewmodelu za druge prikaze
Dodajte `Create` prikaz (`Create.cshtml`) za entitet `Song`.
- _Add View_, _Razor View_, _Template: Create_, _Model class: SongVM_
- ne trebamo ID, uklonite taj odjeljak iz HTML-a
Upotrijebite predložak `Create`, ažurirajte akciju `POST Create` tako da prihvaća kao parametar model prikaza `SongVM`.
Dodajte novu pjesmu u bazu podataka.
- za novu pjesmu postavite svojstva: `Name`, `Year`, `GenreId`, `ArtistId`
- pogledajte kako je to napravljeno u `POST Create` za `GenreVM`
Sada možete stvoriti novu pjesmu, ali stvaranje je malo nezgrapno jer koristi FK ID-eve.
> Kada pokrenete i testirate funkcionalnost stvaranja, primijetit ćete da `GenreName` i `ArtistName` nemaju smisla, stoga ih uklonite iz predloška.
> Također ćete zamijeniti `GenreId` i `ArtistId` padajućim izbornicima.
### 10.8 Related data: Replace ID textboxes with dropdowns
Za npr. `GenreId`, umjesto oznake `` potrebna vam je oznaka `