MODUL 1 - LEKCIJA 4

.NET Evolucija: Od ASP do .NET Core

Putovanje kroz historiju .NET frameworka i duboko razumijevanje modernih koncepta kao što su Middleware i Dependency Injection.

⏱️ Trajanje: ~60 min 📚 Nivo: Srednji 🎯 Koncepti: Classic ASP, Web Forms, MVC, .NET Core, DI, Middleware

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".

Classic ASP 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.

📜 code: proizvodi.asp
<%
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.

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.

Web Forms ViewState

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.

📜 code: Proizvodi.aspx.cs
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:

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.

MVC Architecture

Jasna separacija odgovornosti: Model-View-Controller

Rad sa bazom podataka (Entity Framework)

Nema više SQL-a u kodu. Koristimo LINQ upite.

📜 code: ProizvodiController.cs
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).

📜 code: ProizvodiApiController.cs
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.

📜 code: ProizvodiController.cs (.NET Core)
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.

📜 code: Program.cs
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.

Middleware Pipeline

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:

  1. Obraditi zahtjev i proslijediti ga sljedećem članu (pomoću next() delegata).
  2. "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.

Dependency Injection Analogy

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).

🏛️ 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":

Service Lifetimes

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.