1. Era Classic ASP-a (VBScript & ADO)
U Classic ASP-u nije bilo pravih klasa ili "objektno-relacionog mapiranja" (ORM). Sve se svodilo na direktno pisanje SQL upita unutar HTML-a. Ovo se zvalo "Spaghetti code".
Prikaz miješanja logike, baze i HTML-a u jednom fajlu
Rad sa bazom podataka (ADO - ActiveX Data Objects)
Programeri su koristili ADODB.Connection za otvaranje veze i Recordset za
čitanje podataka.
<%
Dim objConn, objRS, strSQL
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open "Provider=SQLOLEDB;Data Source=ServerName;Initial Catalog=Baza;User ID=sa;Password=lozinka;"
strSQL = "SELECT Ime, Cijena FROM Proizvodi"
Set objRS = objConn.Execute(strSQL)
Response.Write("<ul>")
While Not objRS.EOF
Response.Write("<li>" & objRS("Ime") & " - " & objRS("Cijena") & " KM</li>")
objRS.MoveNext
Wend
Response.Write("</ul>")
objRS.Close
Set objRS = Nothing
objConn.Close
Set objConn = Nothing
%>
API i Web Servisi u to vrijeme
U ovoj eri, koncept "API-ja" nije bio standardizovan kao danas.
- Raw XML: Ako ste željeli poslati podatke drugom sistemu, napravili biste .asp
stranicu koja umjesto HTML-a ispisuje sirovi XML koristeći
Response.ContentType = "text/xml". - SOAP: Pojavom SOAP protokola, koristile su se glomazne COM+ komponente, što je bilo izuzetno teško za konfigurisanje.
2. ASP.NET Web Forms (C# & ADO.NET) - Naslijeđe u Upravi
Web Forms uvode Code-Behind. Logika baze se seli u C# fajl, a na stranici ostaju kontrole koje "znaju" same da prikažu podatke.
🏛️ Web Forms i Javna Uprava
Ukoliko se zaposlite u državnom sektoru, velika je vjerovatnoća da ćete održavati sisteme (tzv. "Legacy sistemi") pisane prije 10-15 godina upravo u Web Formsima. Mnogi portali e-Uprave, poreski registri i sistemi zdravstvenog osiguranja su građeni u ovoj eri. Danas je ključni zadatak države Digitalna Transformacija – postepeno refaktorisanje ovih gigantskih monolita u moderne, brze ASP.NET Core mikroservise.
Stranica nosi "skriveni ruksak" podataka (ViewState)
Rad sa bazom podataka (ADO.NET & DataBinding)
Umjesto ručnog pisanja HTML-a u petlji, koristili smo kontrole poput GridView.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string connString = ConfigurationManager.ConnectionStrings["MojaBaza"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand("SELECT Ime, Cijena FROM Proizvodi", conn);
conn.Open();
SqlDataReader rdr = cmd.ExecuteReader();
GridViewProizvodi.DataSource = rdr;
GridViewProizvodi.DataBind(); // Magija koja automatski puni tabelu
}
}
}
API i Web Servisi: ASMX i WCF
Ovdje Microsoft uvodi namjenske formate za razmjenu podataka:
- ASMX Web Servisi: Prvi pravi način za kreiranje servisa. Koristili su isključivo
SOAP/XML. Kod: Označite metodu sa
[WebMethod]. - WCF (Windows Communication Foundation): "Svemirski brod" za komunikaciju. Moćan,
ali toliko kompleksan da su konfiguracioni fajlovi (
web.config) često imali stotine linija koda.
3. ASP.NET MVC (Entity Framework & Web API)
Dolazak MVC-a donosi prelazak na Entity Framework (EF) — prvi pravi Microsoftov ORM (Object-Relational Mapper). Baza se više ne posmatra kao set tabela, već kao kolekcija C# objekata.
Jasna separacija odgovornosti: Model-View-Controller
Rad sa bazom podataka (Entity Framework)
Nema više SQL-a u kodu. Koristimo LINQ upite.
public class ProizvodiController : Controller
{
private MojDbContext db = new MojDbContext();
public ActionResult Index()
{
// LINQ upit - čitko i sigurno od SQL injection-a
var proizvodi = db.Proizvodi.Where(p => p.Aktivan == true).ToList();
return View(proizvodi);
}
}
Revolucija: ASP.NET Web API
MVC je uveo poseban tip kontrolera (ApiController) specijalizovan za RESTful servise i
JSON. Ovo je bio trenutak kada web aplikacije prestaju biti "monoliti" i postaju backend za moderne JS
frontende (Angular, React).
public class ProizvodiApiController : ApiController
{
[HttpGet]
public IHttpActionResult GetProizvodi()
{
var data = db.Proizvodi.ToList();
return Ok(data); // Automatski pretvara listu u JSON format
}
}
4. .NET Core (EF Core & Minimal APIs)
.NET Core donosi vrhunac optimizacije. Sve je podređeno performansama i radu na više platformi (Windows, Linux, macOS).
Rad sa bazom podataka (EF Core)
Koncept ostaje sličan MVC-u, ali se uvodi Dependency Injection (DI). Baza se više ne
instancira sa new, već je sistem "ubrizgava" u kontroler.
public class ProizvodiController : ControllerBase
{
private readonly ApplicationDbContext _context;
public ProizvodiController(ApplicationDbContext context) // Dependency Injection
{
_context = context;
}
[HttpGet]
public async Task GetAll()
{
return Ok(await _context.Proizvodi.ToListAsync());
}
}
Šta .NET Core rješava (Problem MVC-a)?
U starom MVC-u, svaki zahtjev je morao proći kroz System.Web.dll, što je bio ogroman i spor
fajl pun naslijeđenog koda iz 90-ih. .NET Core je izbacio System.Web. Umjesto toga, koristi se lagani
Kestrel web server.
Budućnost: Minimal APIs
U najnovijim verzijama (.NET 6/7/8), Microsoft uvodi Minimal APIs. Ako pravite mali servis, više vam ne treba ni kontroler ni komplikovana struktura.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/proizvodi", async (ApplicationDbContext db) =>
await db.Proizvodi.ToListAsync());
app.Run();
Ovo je cijela aplikacija u svega nekoliko linija koda!
📊 Sumarna tabela za tvoj tutorial
| Era | Tehnologija | Baza Podataka | API Format | Glavni Problem |
|---|---|---|---|---|
| Classic ASP | Skripte (VBS) | ADO (Recordset) | Raw XML | Špageti kod, teško održavanje. |
| Web Forms | Kontrole (C#) | ADO.NET (Datasets) | ASMX (SOAP) | Pretežak ViewState, spor render. |
| MVC | Arhitektura | EF (LINQ) | Web API (JSON) | Vezanost za Windows (System.Web). |
| .NET Core | Modularnost | EF Core (DI) | Minimal APIs | Početna kompleksnost učenja DI. |
5. Srce .NET Core sistema – Middleware i Dependency Injection
Ovo poglavlje se fokusira na dva "motora" koji pokreću moderni .NET Core. Bez razumijevanja Middleware-a i Dependency Injection-a (DI), rad u .NET-u se svodi na puko kopiranje koda. Dok su stariji frameworkovi (poput Web Formsa) bili kruti i monolitni, .NET Core je dizajniran kao LEGO set. Vi odlučujete koji dio vam treba i kako će se oni složiti.
1. Middleware Pipeline (Cjevovod zahtjeva)
Zamislite Middleware kao niz "kontrolnih tačaka" ili filtera kroz koje svaki HTTP zahtjev mora proći prije nego što stigne do vašeg koda, i kroz koje se odgovor mora vratiti nazad do korisnika.
Cjevovod zahtjeva: Protok, Next() i Short-circuiting
Kako to funkcioniše?
Kada zahtjev stigne na server, on ulazi u Pipeline. Svaki komad Middleware-a u tom lancu ima dvije opcije:
- Obraditi zahtjev i proslijediti ga sljedećem članu (pomoću
next()delegata). - "Kratko spojiti" (Short-circuit) zahtjev i odmah vratiti odgovor (npr. ako korisnik nije prijavljen, Middleware za autentifikaciju ga odmah odbija i zahtjev uopšte ne stiže do baze podataka).
🏛️ Middleware u praksi: Revizijski trag (Audit Logging)
Zamislimo portal gdje referenti traže podatke građana. Po zakonu, svaka pretraga mora biti logirana. Umjesto da u svakom kontroleru e-Uprave pišete kod za logiranje, vi napišete jedan generalni Audit Middleware.
public async Task InvokeAsync(HttpContext context)
{
// 1. Pričaj sa bazom prije nego proslijediš zahtjev (Zabilježi ko šta traži)
_logger.LogInformation($"Službenik {context.User.Identity.Name} pristupa putanji: {context.Request.Path}");
// 2. Pusti zahtjev da ide dalje u stvarni Controller
await _next(context);
// 3. Ovdje možete reagovati na rezultat (npr. zabilježiti da li je vraćena greška građaninu)
}
Ovaj jedan mali fajl sada presreće SVE zahtjeve u cijeloj državnoj instituciji i garantuje potpunu zakonsku usklađenost sistema, čime sistem postaje transparentan.
Praktični savjet za učenje: Ako želite da vidite Middleware na djelu, pokušajte u
svom projektu namjerno zamijeniti mjesta app.UseRouting() i
app.UseEndpoints(). Aplikacija će prestati raditi. To je najbolji dokaz da je .NET Core
strogo definisan "cjevovod" kroz koji podaci teku tačno određenom putanjom.
2. Dependency Injection (DI) – Ubrizgavanje zavisnosti
Ovo je koncept koji studentima često zadaje najviše glavobolja, a zapravo je vrlo jednostavan ako koristimo analogiju sa restoranom.
DI Container daje Controlleru samo ono što mu treba
Problem: Čvrsto vezivanje (Tight Coupling)
U starim sistemima, ako je vašem kontroleru trebala baza podataka, on bi je sam kreirao:
private readonly Database _db = new Database();
Problem: Šta ako želite promijeniti bazu? Šta ako želite testirati kod bez prave baze? Morate mijenjati kod u svakom kontroleru.
Rješenje: DI (Restoran analogija)
Vi ste kuvar (Kontroler). Treba vam nož (Servis za bazu).
- Bez DI: Vi usred kuhanja izlazite vani, tražite rudu metala, kujete nož i onda se
vraćate da siječete. (Sami pravite zavisnost pomoću
new). - Sa DI: Vi samo kažete: "Meni treba nešto što siječe (Interface)". Menadžer kuhinje (DI Container) vam donosi nož na radni sto. Vi ne znate odakle je došao, vi samo znate da on radi posao.
🏛️ DI u praksi: Sigurna integracija sa CIPS-om
U kontroleru za saobraćajne dozvole, vama treba alat koji provjerava adresu u CIPS bazi građana. Vi ne smijete praviti direktnu konekciju sami.
public class VozackeDozvoleController : ControllerBase
{
private readonly ICipsServis _cips; // Samo tražimo interfejs (Ugovor sa servisom)
// DI Kontejner nam automatski "ubrizgava" tačan zaduženi servis (Kuhinja nam donosi pravog kuhara)
public VozackeDozvoleController(ICipsServis cips)
{
_cips = cips;
}
[HttpGet("{jmbg}")]
public IActionResult ProvjeriAdresu(string jmbg)
{
var adresa = _cips.DohvatiZvanicnuAdresu(jmbg); // Mi samo koristimo servis
return Ok(adresa);
}
}
Glavna ljepota ovog pristupa: Tokom programiranja (testiranja lokalno na
programerskom računaru), DI kontejner vam može ubrizgati neki LažniCipsServis koji
uvijek vraća prolaz i dummy rutu "Obala Kulina Bana 2".
Tako možete razvijati i bezbroj puta testirati portal za vozačke dozvole, bez da ikada imate pristup
pravoj, strogo čuvanoj bazi građanskih podataka!
Životni vijek servisa (Service Lifetimes)
Kada registrujete svoj servis u DI kontejneru, morate mu odrediti "rok trajanja":
Vizuelni prikaz instanci kroz vrijeme
| Životni vijek | Opis | Analogija |
|---|---|---|
| Transient | Kreira se novi objekat svaki put kada ga neko zatraži. | Jednokratne papirne maramice. |
| Scoped | Kreira se jedan objekat po jednom HTTP zahtjevu. | Konobar koji vas služi tokom jedne večere (zahtjeva). |
| Singleton | Kreira se jedan objekat kada aplikacija krene i traje zauvijek. | Glavni sat na zidu restorana – svi gledaju u isti. |
Zašto je ovo studentima interesantno?
- Testabilnost: Zahvaljujući DI-u, umjesto prave baze, u testovima možemo "podmetnuti" lažnu (Mock) bazu. Naš kontroler neće ni primijetiti razliku jer on samo traži "nešto što priča sa bazom".
- Čist kod: Vaše klase postaju manje. One više ne brinu o tome kako se objekti prave, već samo šta ti objekti rade.
- Performanse: .NET Core optimizuje Middleware tako da se izvršavaju samo oni dijelovi koji su neophodni, što ga čini nevjerovatno brzim u odnosu na stari ASP.NET.