UPOTREBA WEB API SERVERA ZA POTREBE DRUGE WEB APLIKACIJE
koristeći GET, POST, PUT, DELETE pozive preko JAVASCRIPT-a
U današnjem digitalnom svetu, aplikacije često moraju da komuniciraju sa drugim aplikacijama ili servisima kako bi funkcionisale ispravno. Na primer, kada koristimo mobilne aplikacije za pretragu proizvoda, rezervaciju hotela ili gledanje vremenske prognoze, ove aplikacije se često povezuju sa serverima koji pružaju potrebne informacije. Ova komunikacija između klijentskih aplikacija (kao što su mobilne ili web aplikacije) i servera obavlja se pomoću Web API-ja (Application Programming Interface).
Web API je skup pravila i protokola koji omogućavaju različitim softverskim sistemima da međusobno komuniciraju preko interneta. Koristeći standardne protokole, kao što je HTTP (Hypertext Transfer Protocol), Web API omogućava aplikacijama da šalju i primaju podatke sa servera na jednostavan i organizovan način.
Web API je skup pravila i protokola koji omogućavaju različitim softverskim sistemima da međusobno komuniciraju preko interneta. Koristeći standardne protokole, kao što je HTTP (Hypertext Transfer Protocol), Web API omogućava aplikacijama da šalju i primaju podatke sa servera na jednostavan i organizovan način.
Uvod u Web API i REST arhitekturu
Web API omogućava razmenu podataka između klijent aplikacija i servera koristeći HTTP protokol. Najčešće se implementira pomoću REST (Representational State Transfer) arhitekture koja koristi standardne HTTP metode za CRUD operacije:
Web API omogućava razmenu podataka između klijent aplikacija i servera koristeći HTTP protokol. Najčešće se implementira pomoću REST (Representational State Transfer) arhitekture koja koristi standardne HTTP metode za CRUD operacije:
- GET: Dohvata podatke sa servera.
- POST: Kreira nove resurse.
- PUT: Ažurira postojeće resurse.
- DELETE: Briše resurse.
Da bi se testirao web API server mogu se koristiti neki od postojećih web klijenata : POSTMAN, OPEN API itd, ali će u ovom članku biti opisano kako se kreira jednostavna ASP.NET Core aplikacija koja se kreira koristeći samo HTML, CSS i Javascript i koja koristi web API aplikaciju kada je potrebno da smešta podatke u bazu , edituje ili potražuje podatke iz baze podataka.
Aplikacija treba da prikazuje listu nekih proizvoda, jednog ili više, da omogući kreiranje novog proizvoda, da menja podatke o proizvodu ili da ga briše iz baze podataka.
Da bi ovo ostvarila aplikacija, koju ćemo u ovom tekstu nazvati "WebAppProductsViewerForWebApi" treba da ostvari zahteve GET, POST, PUT, PATCH, DELETE ka WEB API serveru. Pri tome će obe aplikacije biti potignute na lokalnom računaru, ali će biti na različitom portu.
Adresa WEB API će biti: https://localhost:5001/, dok će web aplikacija koja sa njom komunicira biti podignuta na adresi: https://localhost:5021/
Početna strana ove aplikacije se može videti na sledećoj slici:
Aplikacija treba da prikazuje listu nekih proizvoda, jednog ili više, da omogući kreiranje novog proizvoda, da menja podatke o proizvodu ili da ga briše iz baze podataka.
Da bi ovo ostvarila aplikacija, koju ćemo u ovom tekstu nazvati "WebAppProductsViewerForWebApi" treba da ostvari zahteve GET, POST, PUT, PATCH, DELETE ka WEB API serveru. Pri tome će obe aplikacije biti potignute na lokalnom računaru, ali će biti na različitom portu.
Adresa WEB API će biti: https://localhost:5001/, dok će web aplikacija koja sa njom komunicira biti podignuta na adresi: https://localhost:5021/
Početna strana ove aplikacije se može videti na sledećoj slici:
Na slici se vidi lista proizvoda čiji se podaci nalaze u SQL Server bazi podataka, a sa kojom aplikacija komunicira preko web API servera. Da bi se prikazala pomenuta lista iz javascript-a se upućuje ajax GET zahtev koji vraća podatke o svim proizvodima. Iznad liste je "Istaknut proizvod", dakle jedan proizvod, čiji podaci će iz baze biti dobijeni takođe pomoću GET zahteva ali u ovom slučaju onog koji za poslat id proizvoda vraća podatke o jednom proizvodu.
Takođe se mogu uočiti dugmad "New", "Edit" i "Delete", čijim se klikom otvaraju nove stranice Create,html i Edit.html sa formama za unos u slučaju prva dva, dok se za brisanje(Delete eng.) poziva samo metoda koja je na istoj stranici "Index.html". Ovim se omogućava upućivanje ajax poziva za kreiranje novog(POST), izmenu određenog(PUT ili PATCH), i brisanje određenog proizvoda. Kompletno kreiranje ove aplikacije i analiza se može videti u priloženom video materijalu.
Takođe se mogu uočiti dugmad "New", "Edit" i "Delete", čijim se klikom otvaraju nove stranice Create,html i Edit.html sa formama za unos u slučaju prva dva, dok se za brisanje(Delete eng.) poziva samo metoda koja je na istoj stranici "Index.html". Ovim se omogućava upućivanje ajax poziva za kreiranje novog(POST), izmenu određenog(PUT ili PATCH), i brisanje određenog proizvoda. Kompletno kreiranje ove aplikacije i analiza se može videti u priloženom video materijalu.
Izrada WebAppProductsViewerForWebApi aplikacije-video materijal
video 1 |
video 2 |
video 3 |
video 4 |
Web aplikacija koja prikazuje listu proizvoda, je jednostavna aplikacija koja koristi HTML, CSS i javascript. Takođe koristi i bootstrap framework za stilizovanje i dodavanje funkcionalnosti. Deo početne index.html stranica je prikazana u nastavku, dok se kompletan kod može videti na adresi: github.com/slobodantrs/aspdotnet.git
Statički fajlovi se nalaze u wwwroot folderu, a kako se to podešava kreira pogledajte na strani: Servisiranje statičkih web strana pomoću web servera
Glavna funkcionalnost, odnosno pozivi ka web API aplikaciji koja komunicira sa bazom podataka se odvija u main.js fajlu.
$(document).ready(function () {onStartLoad();}); let table; async function onStartLoad() {//call getData function getData().then((data) => { loadDataList(data); }) .catch((error) => { alert("Unable to get items." + error); });const idFeature=3; getFeatureData(idFeature).then((data) => { prikazFeatureData(data); }) .catch((error) => { alert("Unable to get items." + error); }); //log the data} async function getData() {//await the response of the fetch call /*Poziv GET metode u web API aplikaciji*/ let response = await fetch("https://localhost:5001/products"); //proceed once the first promise is resolved. let data = await response.json(); //proceed only when the second promise is resolved return data;} async function loadDataList(data) {let product_list = document.querySelector("#productList"); table = document.createElement("table"); table.classList.add("productsTable"); product_list.appendChild(table); let i = 0; let row; for (key in data) {} async function getFeatureData(id) {var obj = data[key]; if (obj instanceof Object) {}if (i % 4 == 0) {}row = document.createElement("TR"); row.classList.add("d-flex"); row.classList.add("flex-row"); row.classList.add("justify-content-around"); //It has 4 div elements in a row table.appendChild(row); //Add row in the table} let h1Title = document.createElement("h2"); let priceParagraph = document.createElement("p"); let colorParagraph = document.createElement("p"); let sizeParagraph = document.createElement("p"); let quantityParagraph = document.createElement("p"); let btnDiv=document.createElement("div"); let aEdit=document.createElement("a"); let aDelete=document.createElement("a"); btnDiv.classList.add("d-flex"); aEdit.classList.add("btn"); aEdit.classList.add("btn-success"); aEdit.classList.add("text-white"); aEdit.setAttribute('href','edit.html?id='+obj.productId); aEdit.style.width = '100%'; aEdit.innerText = 'Edit'; aDelete.classList.add("btn"); aDelete.classList.add("btn-danger"); aDelete.classList.add("text-white"); aDelete.style.width = '100%'; aDelete.style.cursor = 'pointer'; aDelete.innerText = 'Delete'; const urlDel='https://localhost:5001/products/Delete/'+obj.productId; aDelete.onclick= function(){Delete(urlDel);}; h1Title.innerHTML = h1Title.innerHTML + obj.name; priceParagraph.innerHTML = priceParagraph.innerHTML + "Price: " + obj.price + " $"; colorParagraph.innerHTML = colorParagraph.innerHTML + "Color: " + obj.color; sizeParagraph.innerHTML = sizeParagraph.innerHTML + "Size: " + obj.size; quantityParagraph.innerHTML = quantityParagraph.innerHTML + "Quantity: " + obj.quantity; let column = document.createElement("TD"); column.appendChild(h1Title); column.appendChild(priceParagraph); column.appendChild(colorParagraph); column.appendChild(sizeParagraph); column.appendChild(quantityParagraph); column.appendChild(btnDiv);/*new*/ btnDiv.appendChild(aEdit);/*new*/ btnDiv.appendChild(aDelete);/*new*/ row.appendChild(column); i++;//await the response of the fetch call /*Poziv GET metode unutar web API aplikacije */ let response = await fetch("https://localhost:5001/products/"+id); //proceed once the first promise is resolved. let data = await response.json(); //proceed only when the second promise is resolved return data;} async function prikazFeatureData(data) {/*var dataArr = data["data"]; varijanta kad se spakuju podaci u JSON */ let nameOfArticleFeature = document.querySelector("#prod1"); let priceOfArticleFeature = document.querySelector("#prodPrice"); nameOfArticleFeature.innerHTML = data.name; priceOfArticleFeature.innerHTML = data.price + " $";} /*New*/ async function Delete(url) {await swal({}title: "Are you sure?", text: "You will not be able to recover this imaginary file!", icon: "warning", buttons: true, dangerMode: true,}).then((willDelete) => {if (willDelete) {});$.ajax({} else { }url: url, dataSrc: function (data) {});var json = JSON.parse(JSON.stringify(data)); return json;}, type: "DELETE", datatype: "json", success: function (data) {if (data.success) {},toastr.success(data.success); window.location.reload();} else {toastr.err(data.message);}
Javascript fajl prikazan iznad je statički fajl koji se nalazi u js folderu, koji je kao i ostali statički fajlovi unutar wwroot foldera. Ovaj fajl je povezan sa index.html stranicom pomoću script taga:
<script type="text/javascript" src="js/main.js"></script>
Prvo se izvršava onStartLoad() funkcija koja zatim zove getData() funkciju. Ona se izvršava asinhrono i ima za cilj da prikupi podatke o proizvodima, pozivajući web API aplikaciju, koja će podatke pročitati iz baze i vratiti Promise objekat. Kada se svi podaci prikupe pomoću json() funkcije se pretvaraju u JSON objekat, a zatim se taj objekat vraća iz funkcije getData() kao njena povratna vrednost.
Ukoliko je status odgovora korektan (200) izvršava se dalje then(data) i podaci prosleđuju funkciji loadDataList(data), u suprotnom će se izvršiti funkcija catch(error) kojoj se prosleđuje poruka o grešci. Ako su podaci uspešno vraćeni iz web API aplikacije dalje se prosleđuju funkciji loadDataList(data), u slučaju potraživanja cele liste proizvoda, a u slučaju potraživanja jednog proizvoda, pozvaće se metoda getFeatureData(idFeature). Obe ove metode treba da podatke postave na index.html stranicu. Prva pravi listu proizvoda, dok druga prikazuje istaknuti artikal čiji je id=3.
Ukoliko je status odgovora korektan (200) izvršava se dalje then(data) i podaci prosleđuju funkciji loadDataList(data), u suprotnom će se izvršiti funkcija catch(error) kojoj se prosleđuje poruka o grešci. Ako su podaci uspešno vraćeni iz web API aplikacije dalje se prosleđuju funkciji loadDataList(data), u slučaju potraživanja cele liste proizvoda, a u slučaju potraživanja jednog proizvoda, pozvaće se metoda getFeatureData(idFeature). Obe ove metode treba da podatke postave na index.html stranicu. Prva pravi listu proizvoda, dok druga prikazuje istaknuti artikal čiji je id=3.
Kroz ovaj primer je pokazano kako web aplikacija koja u ovom slučaju ima funkciju klijenta, i upućuje zahteve web API servisu, potražujući podatke iz neke baze podataka. U ovom slučaju je pokazano kako se preko javacript-a prave ajax GET zahtevi.
Kompletan kod je dat na GitHub-u, dok sledeća tabela prikazuje kako da se formiraju i ostali ajax pozivi ka web API servisu, koji će proizvesti POST, PUT i DELETE zahteve.
Kompletan kod je dat na GitHub-u, dok sledeća tabela prikazuje kako da se formiraju i ostali ajax pozivi ka web API servisu, koji će proizvesti POST, PUT i DELETE zahteve.
WEB APLICATION | WEB API | ||
---|---|---|---|
description | ajax call | called method | returning value |
Zahtev za listu proizvoda | //await the response of the fetch call |
GetAllProducts() |
Task < ActionResult < IEnumerable < Product > > > |
Zahtev za proizvod sa određenim ID-om | "
//await the response of the fetch call |
GetProduct(int id) |
Task < ActionResult < Product > >
|
Unošenje novog proizvoda u bazu podataka | var uriCreate = uri + "/Create"; |
Post(Product product) |
Task < ActionResult < int > > |
Ažuriranje određenog proizvoda | var uriUpdate = uri + "/Update"; |
PutAsync(int id,Product product)
|
Task < ActionResult < int > >
|
Brisanje određenog proizvoda | const urlForDelete="..."; |
DeleteProduct(int id)
|
Task< ActionResult < int > >
|
Kod primeri:
Asinkrona komunikacija sa API-jem
Za asinkronu komunikaciju, možete koristiti fetch ili axios:
Za asinkronu komunikaciju, možete koristiti fetch ili axios:
- Fetch primer:
async function getData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
}
getData();
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
}
getData();
- Ovaj primer koristi fetch za slanje GET zahteva i asinkrono čeka odgovor koristeći async/await.
- Axios primer:
axios.get('https://api.example.com/data')
.then(response => console.log(response.data))
.catch(error => console.error(error));
.then(response => console.log(response.data))
.catch(error => console.error(error));
- Axios pojednostavljuje rad sa API-jem i automatski parsira JSON odgovor.
Sigurnost: Autentifikacija i Autorizacija
Sigurnost u komunikaciji sa Web API-jem je ključna. Dva osnovna koncepta su:
- Autentifikacija potvrđuje identitet korisnika. Jedan od najčešćih mehanizama je korišćenje JWT (JSON Web Tokens) tokena, koji se generiše nakon uspešne prijave korisnika.
- Autorizacija određuje prava korisnika nakon što je identifikovan. JWT tokeni se šalju u Authorization zaglavlju HTTP zahteva, obično u formatu Bearer token, što omogućava API-ju da verifikuje korisničke privilegije.
Dokumentacija i Resursi
Da biste nastavili sa učenjem i usavršavanjem u radu sa Web API-jem i povezanim tehnologijama, ovde su neki korisni resursi i dokumentacija koje možete istražiti:
- ASP.NET Core Dokumentacija
- Zvanična dokumentacija za ASP.NET Core. Ovdje možete pronaći sve što vam je potrebno za rad sa ASP.NET Core, uključujući vodiče, reference i primjere.
- Mozilla Developer Network (MDN) - JavaScript
- MDN nudi sveobuhvatan vodič za JavaScript, uključujući osnovne koncepte, funkcije i primjere.
- Postman Dokumentacija
- Postman je popularan alat za testiranje Web API-ja. Njihova dokumentacija pruža informacije o tome kako koristiti Postman za slanje zahteva i testiranje vašeg API-ja.
- OpenAPI Specification
- OpenAPI (prethodno poznat kao Swagger) je standard za dokumentaciju REST API-ja. Ovdje možete naučiti kako koristiti OpenAPI za kreiranje i dokumentovanje vaših API-ja.
- JavaScript Tutorijali na W3Schools
- W3Schools nudi jednostavne tutorijale za JavaScript, uključujući osnovne i napredne tehnike.
- Axios Dokumentacija
- Axios je popularna biblioteka za pravljenje HTTP zahteva u JavaScript-u. Dokumentacija uključuje vodiče i primjere za korišćenje Axiosa.
Pregled i Finalne Napomene
Na kraju, evo ključnih tačaka koje smo pokrili:
- Važnost Web API-ja
- Razumevanje kako Web API omogućava komunikaciju između klijentskih aplikacija i servera pomoću HTTP protokola.
- REST Arhitektura
- Upoznavanje sa osnovnim metodama REST arhitekture (GET, POST, PUT, DELETE) i njihovom primenom u realnim scenarijima.
- Implementacija Web API-ja
- Kako kreirati jednostavnu ASP.NET Core aplikaciju koja koristi Web API i kako testirati Web API koristeći alate kao što su POSTMAN i OPEN API.
- Praktičan Primer
- Demonstracija kako Web API može upravljati proizvodima u aplikaciji, uključujući primene GET, POST, PUT, PATCH i DELETE zahteva.
- Sigurnost u Web API-ju
- Osnovne informacije o autentifikaciji i autorizaciji, kao i o važnosti HTTPS-a za sigurnu komunikaciju.