ASP.NET Core: statičke strane i jednostavni web servisi
Lekcija 2 od 7 · ASP.NET Core
Server iz prve lekcije proširujemo na dva načina: da šalje gotove HTML, CSS i JavaScript fajlove iz foldera wwwroot i da odgovara podacima u formatu JSON. Na kraju ih spajamo – stranica JavaScript-om traži podatke od servera.
Pre nego što počneš: potrebno predznanje – prvi web server, API i JSON. Kako da učiš: radi u svom projektu korak po korak i posle svake izmene pokreni aplikaciju; zadatak na kraju prvo uradi sam/a. Kod je u C#-u za .NET 8 ili noviji (preporuka: aktuelna LTS verzija); naziv fajla je u komentaru na vrhu svakog primera.
Statičke strane: wwwroot
// Program.cs
using System.Globalization;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseDefaultFiles(); // zahtev za "/" traži index.html
app.UseStaticFiles(); // šalje fajlove iz foldera wwwroot (HTML, CSS, JS, slike)
// JSON servisi (ispod)
var sr = new CultureInfo("sr-Latn-RS");
app.MapGet("/api/vreme", () => new
{
vreme = DateTime.Now.ToString("HH:mm:ss"),
dan = DateTime.Now.ToString("dddd", sr) // "petak"
});
app.MapGet("/api/zdravo/{ime}", (string ime) => new { poruka = $"Zdravo, {ime}!" });
app.MapGet("/api/zbir", (int a, int b) => new { a, b, zbir = a + b }); // /api/zbir?a=2&b=3
app.Run();
Napravi folder wwwroot u korenu projekta. Redosled je važan: UseDefaultFiles mora biti preUseStaticFiles. Ovi pozivi su middleware – delovi kroz koje svaki zahtev prolazi redom, kao kroz traku u fabrici.
Web servisi koji vraćaju JSON
Zahtev
Odgovor
GET /api/vreme
{"vreme":"14:05:31","dan":"petak"}
GET /api/zdravo/Ana
{"poruka":"Zdravo, Ana!"}
GET /api/zbir?a=2&b=3
{"a":2,"b":3,"zbir":5}
GET /api/zbir?a=dva
400 Bad Request – a nije ceo broj
Kada funkcija vrati objekat, ASP.NET Core ga sam pretvori u JSON (imena polja malim početnim slovom). Parametri se uzimaju iz putanje ({ime}) ili iz upita (?a=2) – tip parametra (int) odmah proverava unos. Ovo je isti JSON iz lekcije Šta je API.
Stranica koja koristi servis
<!-- wwwroot/index.html -->
<!DOCTYPE html>
<html lang="sr">
<head><meta charset="utf-8"><title>Moj server</title></head>
<body>
<h1>Dobro došli</h1>
<p>Danas je <span id="dan">…</span>, a tačno vreme je <span id="vreme">…</span>.</p>
<button id="osvezi">Osveži</button>
<script>
async function ucitaj() {
const odgovor = await fetch("/api/vreme"); // ista adresa servera, pa samo putanja
const podaci = await odgovor.json();
document.getElementById("dan").textContent = podaci.dan;
document.getElementById("vreme").textContent = podaci.vreme;
}
document.getElementById("osvezi").addEventListener("click", ucitaj);
ucitaj();
</script>
</body>
</html>
Statička strana i servis su u istoj aplikaciji: HTML stiže kao fajl, a podaci kao JSON. Tako rade i veće aplikacije – razlika je samo u broju servisa.
Statičko ili dinamičko
Statički fajl
Web servis (endpoint)
odakle
folder wwwroot
funkcija u Program.cs ili kontroleru
isti za sve
da
ne – zavisi od parametara, vremena, baze
primer
index.html, stil.css
/api/vreme, /api/proizvodi
Videi iz prve verzije lekcije
Napomena uz video: snimljen je za prvu verziju lekcija (.NET 5/6, klasa Startup, SQL Server i Dapper). Ideje su iste, ali je kod na ovoj strani pisan za današnji .NET (sve u Program.cs) – kada se razlikuju, važi kod sa strane.
Zadaci za vežbu
Za svaki zadatak postoji primer, uputstvo i rešenje.
ZADATAK 01Težina: srednje
Kalkulator sa servisom
Dodaj servis /api/racunaj?a=…&b=…&op=… koji za op = +, -, *, / vraća rezultat, a za deljenje nulom ili nepoznatu operaciju odgovor 400. Napravi i stranu kalkulator.html koja ga koristi.
Uputstvo
U upitu se + šalje kao %2B – u JavaScript-u koristi encodeURIComponent(op). Za grešku vrati Results.BadRequest("..."), a za uspeh Results.Ok(new { rezultat }).
Rešenje
// Program.cs
app.MapGet("/api/racunaj", (double a, double b, string op) => op switch
{
"+" => Results.Ok(new { rezultat = a + b }),
"-" => Results.Ok(new { rezultat = a - b }),
"*" => Results.Ok(new { rezultat = a * b }),
"/" when b != 0 => Results.Ok(new { rezultat = a / b }),
"/" => Results.BadRequest("Deljenje nulom."),
_ => Results.BadRequest("Nepoznata operacija.")
});
<!-- wwwroot/kalkulator.html (deo) -->
<input id="a" type="number"> <select id="op"><option>+</option><option>-</option><option>*</option><option>/</option></select>
<input id="b" type="number"> <button id="izracunaj">=</button> <span id="rez"></span>
<script>
document.getElementById("izracunaj").addEventListener("click", async () => {
const a = document.getElementById("a").value, b = document.getElementById("b").value;
const op = encodeURIComponent(document.getElementById("op").value);
const odg = await fetch(`/api/racunaj?a=${a}&b=${b}&op=${op}`);
document.getElementById("rez").textContent = odg.ok ? (await odg.json()).rezultat : await odg.text();
});
</script>
Česte greške i saveti
Fajlovi van foldera wwwroot se ne šalju – to je i zaštita (npr. appsettings.json nije dostupan spolja).
UseDefaultFiles ne šalje fajl sam – samo prepravlja adresu; zato mora pre UseStaticFiles.
U ASP.NET Core-u se imena JSON polja pišu malim početnim slovom (dan), iako je u C#-u svojstvo Dan.
Proveri znanje
Otvori kviz
Statičke strane i servisi
1. Iz kog foldera ASP.NET Core šalje statičke fajlove?
2. Šta vraća servis koji iz funkcije vrati objekat new { zbir = 5 }?
3. Kakav odgovor dobija /api/zbir?a=dva ako je parametar a tipa int?
SERVISIRANJE STATIČKIH WEB STRANA POMOĆU WEB SERVERA
Statičke web stranice su ključne za jednostavne aplikacije i informativne sajtove. Ovaj tekst objašnjava kako web serveri, poput Apache i Nginx, mogu efikasno isporučivati statičke stranice. Pokrivene su sigurnosne preporuke, optimizacija performansi kroz kompresiju i keširanje, kao i primeri konfiguracije za popularne web servere.Prethodna aplikacija se može proširiti za opsluživanje statičkih web strana. U prethodnom primeru, na zahtev unesen u polju za adrese u web pregledaču:
http://localhost:5000
proces tj. web aplikacija je odgovorila na zahtev vraćajući pozdravnu poruku i sistemsko vreme. Aplikacija se može proširiti tako što joj se dodaju statičke web strane o okviru nekog novog foldera npr. wwwroot koji se nalazi u okviru root foldera aplikacije. Te strane zapravo html strane npr: Kontakt.html, Index.html, Vesti.html, Studenti.html
Sada će zahtev tj. URL za poziv web aplikaciji(Http web serveru) koji treba da vrati sadržaj ovih strana biti npr:
http://localhost:5000/Studenti.html
ili
http://localhost:5000/Kontakt.html
Da bi web server vraćao ove stranice na zahtev klijenta potrebno je u Startup.cs fajlu u okviru Configure metode dodati sledeće dve linije koda:
app.UseDefaultFiles();
app.UseStaticFiles();
Na ovaj način je web serveru rečeno da koristi podrazumevanu lokaciju za statičke fajlove, a to je wwwroot.UseStaticFile() naredba je potrebna da bi se koristili statički fajlovi: html, javascript, css itd. Kako kreirati ovakvu web aplikaciju pomoću VS Code- alata pogledajte u sledećem videu:
Video 1: ASP NET Core: Servisiranje statičkih web strana
Razlika između statičkih stranica i dinamičkih web servisa:
Statičke web stranice sadrže unapred definisane HTML, CSS i JavaScript fajlove koji se ne menjaju prilikom svakog učitavanja. One su idealne za jednostavne informativne sajtove. Dinamički web servisi, s druge strane, odgovaraju na zahteve generisanjem sadržaja u realnom vremenu, poput API poziva. Umesto fiksnih stranica, web servisi vraćaju podatke, koji mogu biti različiti u zavisnosti od ulaza, poput trenutnog vremena ili pretrage korisnika. ASP.NET Core omogućava lako kreiranje ovih dinamičkih servisa.
Web servisi u asp.net core tehnologiji
U prethodnim primerima je opisano kako se kreira jednostavan web server koji vraća tekst ili html stranu na zahtev od strane web pregledača, ali je ponekad neophodno da se kreira web servis. Web serevis je aplikacija koja na zahtev od strane pregledača šalje podatak ili skup podataka a ne html stranu. Primer jednostavnog web servisa je servis koji vraća trenutno vreme sa servera. Ako se u google pretraživaču ukuca neka ključna reč za pretragu npr „Tesla“, google-ov web servis će onda izvršiti najverovatnije neku funkciju kojoj se kao parametar prosleđuje reč „Tesla“ i koja promalazi niz sličnih reči, npr. tesla, teslić, teslin transformator itd i koji se vraća kao odgovor na zahtev web pregledaču.
Video 1: ASP NET Veb servisi
Kreiranje kostura aplikacije se vrši pomoću komande u command promptu:
dotnet new web
Web servis koji vraća sistemsko vreme na serveru je zapravo bio kreiran u nekom od prethodnih primera, dodavanjem naredbe MapGet() objekta klase koja implementira interfejs IEndpointRouteBuilder i koja mapira poziv url-a:
http://localhost:5000/time
na web servis koji prikazuje sistemsko vreme, vidi sliku:
Slika 1: Web servisi u asp.net core- Prikaz sistemskog vremena
Pomoću naredbi: endpoint.MapGet() mogu se dodati i drugi web servisi kao npr. servis koji za poziv http://localhost:5000/day
http://localhost:5000/day
vraća dan u nedelji, što se može videti na sledećoj slici:
Slika 2: Web servisi u asp.net core- Prikaz dana u nedelji
Ako bi smo sada želeli da pozovemo web servis i pri tome mu prosledimo parametar npr. pozivom preko web pregledača koristeći sledeći URL:
http://localhost:5000/hello?name=Mihajlo
onda bi u implementaciji web servisa morali da izvučemo prethodno poslat parametar name=Mihajlo koji predstavlja ime koje treba pridodati pozdravnoj poruci. Na sledećoj slici je prikazan kod koji će to omogućiti:
Slika 4: Web servisi u asp.net core- prikaz pozdrava sa imenom izvučenim iz Querry-ja kao parametrom
Da bi izvukli ime, kreiramo prvo promenljivu “name”, koju ćemo izvući iz context.Request objekta pomoću osobine(Property) Querry koja je zapravo skup parametara koji se definišu u URL adresi poziva posle „?“. Vrednost paramera „name“ izvlačimo iz skupa pristupom preko naziva parametra Querry[„name”]. Primer pokretanja:
Slika 5: Web servisi u asp.net core- prikaz pozdrava sa imenom izvučenim iz Querry-ja kao parametrom- prikaz
Sigurnosne preporuke za servisiranje statičkih web stranica
Koristite HTTPS: Implementacija HTTPS-a osigurava da su svi podaci šifrovani tokom prenosa između servera i klijenta. Ovo je ključno za zaštitu korisničkih podataka, čak i kod statičkih stranica.
SSL/TLS sertifikati: Osigurajte da vaš server koristi SSL/TLS sertifikate kako bi garantovao siguran kanal komunikacije. Možete dobiti besplatne SSL sertifikate pomoću servisa kao što je Let’s Encrypt.
HTTP stroga politika transportne sigurnosti (HSTS): Omogućava automatsko usmeravanje svih HTTP zahteva na HTTPS, čime se sprečava upotreba nesigurnih veza.
Zaštita od napada: Omogućite zaštitu od DDoS napada koristeći firewall i load balancing tehnologije.
Kompresija i keširanje
Kompresija: Web serveri poput Apache i Nginx mogu automatski kompresovati statičke fajlove korišćenjem kompresije kao što je Gzip ili Brotli. Ovo smanjuje veličinu fajlova (HTML, CSS, JS) i ubrzava učitavanje stranice.
Keširanje: Definišite zaglavlja za keširanje resursa kako bi se smanjila potreba za ponovnim preuzimanjem. Koristite Cache-Control i Expires za dugotrajno keširanje.
ExpiresActive On
ExpiresByType text/html "access plus 1 hour"
ExpiresByType image/jpeg "access plus 1 month"
Kompresija (mod_deflate): Ovaj modul kompresuje odgovore (HTML, CSS, JS) koristeći Gzip, smanjujući veličinu podataka koji se prenose između servera i klijenta.
Keširanje (mod_expires): Definiše koliko dugo pretraživač treba da kešira resurse (npr. slike), što poboljšava performanse smanjenjem zahteva prema serveru.
gzip on: Aktivira Gzip kompresiju za određene tipove sadržaja (CSS, JavaScript).
location blok: Postavlja pravila keširanja za statičke fajlove poput slika i CSS fajlova, omogućujući keširanje do 30 dana.
Praktični koraci za implementaciju HTTPS-a i SSL sertifikata:
Nabavka SSL/TLS sertifikata: Sertifikati mogu biti kupljeni od ovlašćenih sertifikacionih autoriteta (CA) ili besplatno putem servisa kao što je Let's Encrypt.
Podešavanje za Apache:
sudo a2enmod ssl
sudo a2ensite default-ssl
sudo service apache2 reload Zatim, u Apache konfiguracionom fajlu (npr. /etc/apache2/sites-available/default-ssl.conf), postavite putanju do sertifikata:SSLCertificateFile /path/to/your_domain_name.crt
SSLCertificateKeyFile /path/to/your_private.key 3. Podešavanje za Nginx: U Nginx konfiguracionom fajlu:server {
listen 443 ssl;
server_name your_domain.com;
ssl_certificate /path/to/your_domain_name.crt;
ssl_certificate_key /path/to/your_private.key;
} Ova konfiguracija aktivira SSL/TLS na serveru. 4. Preusmeravanje HTTP na HTTPS: U Nginx-u ili Apache-u, dodajte pravilo za preusmeravanje svih HTTP zahteva na HTTPS, osiguravajući sigurnu komunikaciju. Nakon postavljanja, važno je redovno obnavljati SSL sertifikate i testirati HTTPS vezu koristeći alate kao što su SSL Labs za proveru sigurnosti.
Koristimo kolačiće da bismo vam pružili najbolje moguće iskustvo. Takođe nam omogućavaju da analiziramo ponašanje korisnika kako bismo stalno poboljšavali veb lokaciju za vas.