📜 Historijski pregled (Timeline)
Razumijevanje historije .NET-a je bitno jer u današnjem poslu zadatak programera, arhitekata, dizajnera neće uvijek biti kreiranje sistema od nule (Greenfield), već često održavanje i nadogradnja sistema pisanih prije 15 godina (Legacy).
Era "Spaghetti" koda (VBScript)
Nije postojala separacija odgovornosti. HTML kod za izgled dugmeta, C# logika i SQL upit prema bazi su pisani u istom fajlu. Održavanje ovakvih sistema danas je noćna mora jer izmjena dizajna često slučajno pruzrokuje grešku u radu s bazom.
Zatvorenost i Težina (ViewState)
Rođen je "Code-Behind". HTML stranica i C# logika su konačno razdvojeni. Microsoft je ovo dizajnirao da olakša posao developerima desktop aplikacija - mogli su "vući" dugmad na ekran a sistem je generisao kod. Međutim, ovo je stvorilo tkz. ViewState fenomen - sistem je morao pamtiti stanje svakog dugmeta i to slao kroz mrežu. Stranice su postale masivne i veoma spore.
Red u haosu i Web API
Microsoft usvaja čistu Arhitekturu: Model (podaci), View (HTML prikazi), Controller (mozak koji upravlja operacijama). Ovdje se gasi ViewState. Kasnije verzije uvode ASP.NET Web API za isporuku JSON formata, označavajući kraj dominacije isključivog HTML renderisanja sa servera.
Revolucija: Cross-Platform & Open Source
Najveća tektonska promjena. Stari .NET Framework je radio isključivo na Windows Serverima koji su
skupi. .NET Core je napisan od nule! Sada se ASP.NET instalira i radi
besprijekorno na Linux i Docker kontejnerima. Performanse su brutalno ubrzane jer je izbačen
arhaični System.Web modul.
Ujedinjenje (Unified .NET)
Microsoft briše sufiks "Core". .NET 5, 6, 7 i 8 ujedinjuju sve biblioteke u jednu snažnu cjelinu sposobnu za Web, Desktop, Mobilne (MAUI), AI i IoT aplikacije. Uvode se Minimal API-ji gdje se cijeli mikroservis može napisati u svega 4 reda koda.
🔄 Srce sistema 1: Middleware Pipeline
U modernom .NET-u, kada API Gateway pošalje HTTP zahtjev u vašu aplikaciju, zahtjev ne ide direktno do vašeg koda (Controllera). On prvo mora pročitati kroz Middleware Pipeline.
Šta je Middleware?
Middleware su mali komadići "presretačkog" koda usklađeni u liniju. Svaki modul prima zahtjev, obrađuje ga, i onda ima samo dvije opcije:
- Proslijediti taj modifikovani zahtjev sljedećem modulu pomoću komande
next() - Odbaciti (Short-circuit) zahtjev i direktno ga ižbaciti natrag klijentu. (Npr. Middleware za autentifikaciju prepoznaje hakerski napad i trenutno baca 401 grešku bez opterećenja procesora.)
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// ----- MIDDLEWARE PIPELINE POČINJE OVDJE (Redoslijed je bitan!) -----
// 1. Ako se kod sruši, ovaj middleware hvata grešku i lijepo je formatira, umjesto da sruši server.
app.UseExceptionHandler("/Home/Error");
// 2. Samo ako tražimo sliku ili CSS, ovaj middleware ih šalje i prekida dalji tok!
app.UseStaticFiles();
// 3. Obavezno prosljeđivanje na HTTPS
app.UseHttpsRedirection();
// 4. Autentifikacija: Ko je korisnik?
app.UseAuthentication();
// 5. Autorizacija: Smije li korisnik pristupiti putanji na koju je krenuo?
app.UseAuthorization();
// 6. Rutiranje: Pronalazi odgovarajući Controller (npr. PredmetiController)
app.MapControllers();
app.Run();
Zašto je ovo genijalno? Ako vaša institucija traži zakonsko zabilježenje baš svake
akcije (Audit Log), vi ne pišete kod za logiranje u stotine Controllera. Vi jednostavno napravite svoj
Custom Middleware app.UseGrađanskiAuditLogger() i stavite ga u pipeline! Svi zahtjevi ga
moraju proći.
💉 Srce sistema 2: Dependency Injection (DI)
Dependency Injection (Ubrizgavanje zavisnosti) rješava najveći problem starih sistema – Čvrsto Vezivanje (Tight Coupling).
❌ Bez DI (Stari Način)
Vaš kontroler direktno zavisi od konkretne klase. Sam otvara konekciju ka bazi.
public class PorezController {
public void Izracunaj() {
// Tightly coupled!!
var db = new SqlServerBaza();
db.Snimi();
}
}
Problem: Ako ministarstvo odluči preći sa SQL na Oracle bazu, morat ćete u 540 fajlova tražiti i mijenjati riječ "SqlServerBaza". Također, ne možete napisati automatski Test za ovaj Controller jer stalno udara pravu bazu.
✅ Sa DI (.NET Standard)
Vaš kontroler zavisi od UGOVORA (Interface). Ne zna ko mu donosi alat.
public class PorezController {
private readonly IBaza _db;
// DI kontejner OVDJE Vam donosi alat!
public PorezController(IBaza db) {
_db = db;
}
public void Izracunaj() {
_db.Snimi(); // Kontrolera ne zanima šta je ispod.
}
}
Rješenje: U Program.cs samo jednom napišemo
builder.Services.AddScoped<IBaza, OracleBaza>(). Sada se cijela javna
aplikacija adaptirala bez ijedne izmjene u Kontrolerima!
Trajanje ubačenog servisa (Service Lifetimes)
Kontejneru (.NET-ovom "magacinu alata") moramo reći koliko dugo da pamti alat (servis) koji mu tražimo:
- Transient (Kratkotrajni):
AddTransient(). Kao "jednokratna maramica". Svaki put kad neko (klasa, kontroler, drugi servis) zatraži ovaj servis, dobije potpuno novu instancu. Odlično za lagane, neovisne kalkulacije. - Scoped (Ograničeni):
AddScoped(). Standard za baze podataka i web pretraživanja! Kao "dnevna karta". Unutar jednog HTTP zahtjeva (od klika u browseru dok ne dobiješ odgovor), svi koji traže ovaj servis dobiće istu instancu. Čim završi taj request, instanca se briše. - Singleton (Jedinstveni):
AddSingleton(). Kao "kancelarijski inventar". Kreira se jednom kada se aplikacija pokrene i svi korisnici (i svi requesti) dijele tu jednu te istu instancu dok se server ne ugasi. Odlično za globalne stvari, ali opasno: pazite na miješanje korisničkih podataka! (Thread safety)