📖 Uvod: Zašto AJAX u javnoj upravi?
AJAX (Asynchronous JavaScript and XML) je tehnika koja omogućava web aplikacijama da asinkrono komuniciraju sa serverom. U kontekstu javne uprave (npr. registar zaposlenih, e-Građanin portali), AJAX je ključan za kreiranje brzih i responzivnih korisničkih interfejsa.
Umjesto da se cijela stranica ponovo učitava prilikom svake akcije (npr. promjena statusa dokumenta, validacija JMBG-a, pretraga predmeta), AJAX omogućava osvježavanje samo specifičnog dijela ekrana. Ovo drastično smanjuje opterećenje servera i štedi bandwidth, što je kritično za sisteme sa hiljadama istovremenih korisnika.
🔄 ASP.NET Unobtrusive AJAX
ASP.NET MVC donosi koncept Unobtrusive AJAX-a (Nenametljivi AJAX). Umjesto pisanja
kompleksnog JavaScript koda unutar HTML elemenata, MVC koristi HTML5 data-* atribute kako
bi označio elemente koji zahtijevaju AJAX ponašanje. jQuery skripta čita te atribute i automatski
presreće submit forme.
Da bi ovo radilo, potrebno je uključiti paket Microsoft.jQuery.Unobtrusive.Ajax u vaš
projekat.
Primjer iz prakse: Pretraga organa uprave
Ukoliko imamo ogromnu listu svih javnih ustanova i ministarstava, pretraga sa osvježavanjem cijele
stranice je spora. Koristit ćemo Ajax.BeginForm za brzu i efikasnu pretragu.
@* Ne zaboravite uključiti skriptu: <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script> *@
@using (Ajax.BeginForm("Search", "Ministry",
new AjaxOptions
{
UpdateTargetId = "ministryResults", // ID elementa gdje se ubacuje PartialView
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace, // Mijenja sadržaj meta elementa
LoadingElementId = "loadingIndicator", // Pokazuje spinner dok se učitava
OnFailure = "showErrorMsg" // Poziva JS funkciju u slučaju greške
}))
{
<div class="input-group">
@Html.TextBox("query", null, new { @class = "form-control", placeholder = "Unesite naziv institucije..." })
<span class="input-group-btn">
<button type="submit" class="btn btn-primary">Pretraži</button>
</span>
</div>
}
<!-- Indikator učitavanja -->
<div id="loadingIndicator" style="display:none;" class="text-info">
<i class="fa fa-spinner fa-spin"></i> Pretraživanje baze podataka...
</div>
<!-- Ovdje će se učitati rezultati -->
<div id="ministryResults" class="mt-3">
@* Sadržaj će biti zamijenjen sa PartialView-om kojeg vraća kontroler *@
</div>
Kontroler koji obrađuje ovaj zahtjev treba vratiti PartialView (djelimični HTML), a ne cijeli View:
public class MinistryController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
[HttpGet]
public ActionResult Search(string query)
{
// Simulacija kašnjenja servera radi prikaza Loading indikatora
System.Threading.Thread.Sleep(500);
var results = db.Departments
.Where(d => string.IsNullOrEmpty(query) || d.DepartmentName.Contains(query))
.ToList();
// Vraća samo HTML strukturu za rezultate, ne i Layout stranicu!
return PartialView("_MinistrySearchResults", results);
}
}
📡 Manuelni jQuery AJAX
Ponekad Ajax.BeginForm nije dovoljan, jer trebamo finiju kontrolu nad podacima, asinkrone
validacije polja pri gubitku fokusa (blur) ili slanje JSON podataka. Tada koristimo čisti jQuery AJAX.
Primjer: Validacija JMBG-a na klijentu
Kada službenik unosi novog zaposlenog, idealno je da se odmah nakon unosa JMBG-a provjeri da li takva osoba već postoji u sistemu, a ne tek kad se klikne "Spasi".
$(document).ready(function() {
$('#JMBG').on('blur', function() {
var unesenJmbg = $(this).val();
var errorSpan = $('#jmbgError');
if (unesenJmbg.length === 13) {
$.ajax({
url: '@Url.Action("CheckJmbgExists", "Employee")', // Sigurno generisanje URL-a
type: 'POST',
dataType: 'json',
data: { jmbg: unesenJmbg },
success: function(response) {
if (response.exists) {
errorSpan.text('Zaposlenik sa ovim JMBG (' + response.name + ') već postoji!');
errorSpan.removeClass('text-success').addClass('text-danger');
$('#btnSubmit').prop('disabled', true);
} else {
errorSpan.text('JMBG je slobodan za unos.');
errorSpan.removeClass('text-danger').addClass('text-success');
$('#btnSubmit').prop('disabled', false);
}
},
error: function(xhr, status, error) {
console.error("Greška pri komunikaciji sa serverom: " + error);
errorSpan.text('Nije moguće provjeriti JMBG trenutno.');
}
});
}
});
});
Kontroler koji odgovara na ovaj POST zahtjev vraća JSON objekat koristeći Json() metodu:
[HttpPost]
public JsonResult CheckJmbgExists(string jmbg)
{
var employee = db.Employees.FirstOrDefault(e => e.JMBG == jmbg);
if (employee != null)
{
return Json(new { exists = true, name = employee.FirstName + " " + employee.LastName });
}
return Json(new { exists = false });
}
✅ Zaključak i najbolje prakse
💡 Preporuke za državne sisteme
- Optimizirajte pretrage: Koristite AJAX za sve forme pretraživanja registara kako biste smanjili payload prenesen kroz mrežu.
- Feedback korisniku: Uvijek obezbijedite vizuelni indikator (spinner) tokom AJAX zahtjeva, kako službenik ne bi dvaput kliknuo dugme.
- Fallback: Iako danas svi browseri podržavaju JavaScript, osigurajte da rutiranje i kontroleri rade i bez AJAX-a (tzv. graceful degradation) ukoliko sigurnosne politike institucije blokiraju skripte.